mina-archive-sdk 0.0.1

Rust SDK for interacting with Mina Archive Node GraphQL endpoints
Documentation

mina-archive-sdk

Rust SDK for Mina Protocol's Archive Node GraphQL endpoint.

Companion to the daemon-targeting mina-sdk crate. This crate targets the separate archive endpoint defined by o1-labs/Archive-Node-API (events, actions, blocks, network state).

Install

[dependencies]
mina-archive-sdk = "0.0.1"
tokio = { version = "1", features = ["full"] }

Tested on Rust stable.

Quick start

use mina_archive_sdk::{ArchiveClient, BlockStatusFilter, EventFilterOptionsInput};

#[tokio::main]
async fn main() -> mina_archive_sdk::Result<()> {
    let client = ArchiveClient::new("https://archive.example/graphql");

    let events = client.get_events(
        EventFilterOptionsInput::for_address("B62q...")
            .status(BlockStatusFilter::Canonical)
            .from(100)
            .to(200),
    ).await?;

    for group in events {
        let height = group.block_info.map(|b| b.height).unwrap_or(-1);
        let count = group.event_data.map(|d| d.len()).unwrap_or(0);
        println!("block {height}: {count} event(s)");
    }
    Ok(())
}

API

Each method on ArchiveClient maps 1:1 to a GraphQL query in the Archive-Node-API schema:

Method Returns Description
get_events(input) Vec<EventOutput> Events emitted by a zkApp account.
get_actions(input) Vec<ActionOutput> Actions dispatched from a zkApp account.
get_network_state() NetworkStateOutput Archive's max canonical / pending block heights.
get_blocks(opts) Vec<Block> Blocks filtered by height/date range and chain status.
query(gql) builder Arbitrary GraphQL through the same retry path.
execute_query(gql, vars, name) serde_json::Value Low-level escape hatch returning the raw data field.

Configuration

use std::time::Duration;
use mina_archive_sdk::{ArchiveClient, ClientConfig};

let client = ArchiveClient::with_config(ClientConfig {
    graphql_uri: "https://archive.example/graphql".to_string(),
    retries: 5,
    retry_delay: Duration::from_secs(10),
    timeout: Duration::from_secs(60),
});

Currency

Currency wraps nanomina amounts in a u64 for safe parsing of coinbase / fee / user-command values:

use mina_archive_sdk::Currency;

let coinbase = Currency::from_graphql("720000000000").unwrap();
assert_eq!(coinbase.mina(), "720.000000000");

let fee = Currency::from_mina("0.01").unwrap();
let total = coinbase + fee;

Errors

All fallible operations return Result<T> over the Error enum. Match on variants:

use mina_archive_sdk::{ArchiveClient, Error, EventFilterOptionsInput};

# async fn example() -> mina_archive_sdk::Result<()> {
let client = ArchiveClient::new("https://archive.example/graphql");
match client.get_events(EventFilterOptionsInput::for_address("B62q...")).await {
    Ok(events) => println!("{} groups", events.len()),
    Err(Error::Graphql { messages, .. }) => eprintln!("server rejected: {messages}"),
    Err(Error::Connection { attempts, .. }) => eprintln!("unreachable after {attempts} tries"),
    Err(Error::MissingField { field, .. }) => eprintln!("schema mismatch: {field}"),
    Err(e) => eprintln!("error: {e}"),
}
# Ok(())
# }

Examples

ARCHIVE_GRAPHQL_URI=https://archive.example/graphql cargo run --example network_state

See examples/:

  • events.rs — query events for an address
  • actions.rs — query actions for an address
  • blocks.rs — get the latest canonical blocks with currency parsing
  • network_state.rs — check archive sync state

Development

cargo build
cargo test --lib --tests       # unit + wiremock tests, no infra needed
cargo fmt --check
cargo clippy --all-targets

Integration tests are #[ignore]d by default — they require a running Archive-Node-API server. CI provisions one in .github/workflows/integration.yml. To run locally:

ARCHIVE_GRAPHQL_URI=http://localhost:8080/ \
  cargo test --test integration_tests -- --ignored --nocapture

Schema sync

schema.graphql is vendored from o1-labs/Archive-Node-API@main. The Schema Drift CI workflow compares them weekly and on PR; on drift, update both schema.graphql and src/types.rs in the same PR.

License

Apache-2.0 — see LICENSE.