Skip to content

Rust SDK

The `prova-agent-sdk` crate brings the full attestation lifecycle to Rust agents: register, attest, batch, revoke — with typed errors and a fluent payload builder. No Anchor client dependency; instructions are built directly.

Install

cargo add prova-agent-sdk

Setup

use prova_agent_sdk::{ProvaClient, ProvaConfig};
use solana_sdk::signature::Keypair;

let client = ProvaClient::new(
    agent_keypair,
    ProvaConfig {
        rpc_url: "https://api.devnet.solana.com".to_string(),
        program_id: None, // defaults to the Devnet deployment
    },
);

Attest

use prova_agent_sdk::{ActionType, AttestParams};

// 1. Hash the action payload (SHA-256 → [u8; 32])
let action_hash = ProvaClient::hash_action(&payload_json);

// 2. Register once per operator
let reg = client.register_agent(&operator_keypair, None).await?;

// 3. Attest a single action
let receipt = client
    .attest(&operator_keypair, action_hash, ActionType::ToolCall, false)
    .await?;
println!("{}", receipt.explorer_url);

// 4. Or batch up to 100 in one transaction
let batch = client
    .batch_attest(&operator_keypair, &[
        AttestParams { action_hash, action_type: ActionType::Decision, privacy_mode: false },
    ])
    .await?;

All write methods return Result<_, ProvaError> — typed errors like BatchLimitExceeded instead of panics, matching idiomatic Rust error handling.

Payload builder

use prova_agent_sdk::AttestationBuilder;
use serde_json::json;

// Fluent builder
let payload = AttestationBuilder::new()
    .action_type(ActionType::ToolCall)
    .payload(json!({ "tool": "jupiter_swap", "amount": "100" }))
    .metadata(json!({ "session": "abc" }))
    .build()?;

// Or typed factories
let tx  = AttestationBuilder::transaction("5Kd3...sig")?;
let tc  = AttestationBuilder::tool_call("fetch_price", json!({ "pair": "SOL/USDC" }))?;
let inv = AttestationBuilder::model_invocation("claude-fable-5", "prompt-hash")?;

Reads & lifecycle

// On-chain reads
let account = client.get_agent_account(&operator_pubkey).await?;
let active  = client.is_agent_active(&operator_pubkey).await;
let (pda, bump) = client.derive_agent_pda(&operator_pubkey);

// Lifecycle management
client.update_policy_root(&operator_keypair, new_root).await?;
client.revoke_agent(&operator_keypair).await?;

API surface

MethodDescription
ProvaClient::new(agent_keypair, config)Build the client. ProvaConfig::default() targets Devnet.
ProvaClient::hash_action(&str) -> [u8; 32]SHA-256 of the payload string.
register_agent(&operator, policy_root)Creates the agent PDA. policy_root: Option<[u8; 32]>.
attest(&operator, hash, action_type, privacy_mode)Single attestation.
batch_attest(&operator, &[AttestParams])1–100 attestations in one transaction.
update_policy_root(&operator, new_root)Rotates the policy Merkle root.
revoke_agent(&operator)Irreversible kill switch.
get_agent_account(&pubkey) / is_agent_active(&pubkey)Read on-chain state.