mina_archive_sdk/lib.rs
1//! Rust SDK for [Mina Protocol's](https://minaprotocol.com) Archive Node
2//! GraphQL endpoint defined by [`o1-labs/Archive-Node-API`](https://github.com/o1-labs/Archive-Node-API).
3//!
4//! Companion to the daemon-targeting [`mina-sdk`](https://crates.io/crates/mina-sdk)
5//! crate. This crate targets the separate **archive** endpoint — events,
6//! actions, blocks, network state.
7//!
8//! # Quick start
9//!
10//! Archive-Node-API serves GraphQL at the root path `/`, not `/graphql`. Pass
11//! the base URL as-is — the SDK never appends a path, so a URL ending in
12//! `/graphql` returns 404.
13//!
14//! ```no_run
15//! # async fn example() -> mina_archive_sdk::Result<()> {
16//! use mina_archive_sdk::{ArchiveClient, BlockStatusFilter, EventFilterOptionsInput};
17//!
18//! let client = ArchiveClient::new("https://archive.example/");
19//! let events = client.get_events(
20//! EventFilterOptionsInput::for_address("B62q...")
21//! .status(BlockStatusFilter::Canonical)
22//! .from(100)
23//! .to(200),
24//! ).await?;
25//!
26//! for group in events {
27//! let height = group.block_info.map(|b| b.height).unwrap_or(-1);
28//! let count = group.event_data.map(|d| d.len()).unwrap_or(0);
29//! println!("block {height}: {count} event(s)");
30//! }
31//! # Ok(())
32//! # }
33//! ```
34//!
35//! # Runtime requirements
36//!
37//! This crate requires a Tokio runtime **with the time driver enabled**.
38//! `reqwest`'s per-request timeout needs it, so on a runtime built without
39//! `enable_time()` every query panics with "A Tokio 1.x context was found, but
40//! timers are disabled". `#[tokio::main]` and `#[tokio::test]` enable it;
41//! a hand-built `Builder::new_current_thread()` does not unless you say so.
42//!
43//! ```no_run
44//! let runtime = tokio::runtime::Builder::new_current_thread()
45//! .enable_time()
46//! .enable_io()
47//! .build()
48//! .unwrap();
49//! # let _ = runtime;
50//! ```
51//!
52//! # Currency
53//!
54//! Coinbase / fee / user-command amounts are returned as nanomina decimal
55//! strings. Use [`Currency`] for safe parsing and arithmetic:
56//!
57//! ```
58//! use mina_archive_sdk::Currency;
59//!
60//! let coinbase = Currency::from_graphql("720000000000").unwrap();
61//! assert_eq!(coinbase.mina(), "720.000000000");
62//!
63//! let fee = Currency::from_mina("0.01").unwrap();
64//! let total = coinbase + fee;
65//! ```
66//!
67//! # Error handling
68//!
69//! All fallible operations return [`Result<T>`](Result), which uses [`Error`].
70//! Match on variants:
71//!
72//! ```no_run
73//! # async fn example() -> mina_archive_sdk::Result<()> {
74//! use mina_archive_sdk::{ArchiveClient, EventFilterOptionsInput, Error};
75//!
76//! let client = ArchiveClient::new("https://archive.example/");
77//! match client.get_events(EventFilterOptionsInput::for_address("B62q...")).await {
78//! Ok(events) => println!("got {} groups", events.len()),
79//! Err(Error::Graphql { messages, .. }) => eprintln!("server rejected the query: {messages}"),
80//! Err(Error::Connection { attempts, .. }) => eprintln!("archive unreachable after {attempts} tries"),
81//! Err(e) => eprintln!("error: {e}"),
82//! }
83//! # Ok(())
84//! # }
85//! ```
86
87mod client;
88mod currency;
89pub mod error;
90pub mod queries;
91mod response;
92mod types;
93
94/// The Archive-Node-API schema version (`MAJOR.MINOR`) this crate speaks.
95///
96/// The server, its schema and this SDK share one major version: the crate
97/// major equals the `SCHEMA_VERSION` major. A server with the same major is
98/// compatible; a higher server minor only adds features this crate may not
99/// wrap yet.
100pub const SCHEMA_VERSION: &str = "2.0";
101
102/// The README's code fences, compiled as doctests.
103///
104/// `RUSTDOCFLAGS`/`RUSTFLAGS` never reached these: in-source examples are
105/// covered by `cargo test --doc`, README fences are covered by nothing, which
106/// is how the quick-start example went on not compiling. `#[cfg(doctest)]`
107/// keeps the README out of the rendered crate docs while still building every
108/// fence in it.
109#[cfg(doctest)]
110#[doc = include_str!("../README.md")]
111pub struct ReadmeDoctests;
112
113pub use client::{ArchiveClient, ClientConfig, GetBlocksOptions, QueryBuilder};
114pub use currency::Currency;
115pub use error::{codes, Error, GraphqlErrorEntry, Result};
116pub use response::Response;
117pub use types::{
118 ActionData, ActionFilterOptionsInput, ActionOutput, ActionStates, Block, BlockInfo,
119 BlockQueryInput, BlockSortBy, BlockStatusFilter, BlockTransactions, EventData,
120 EventFilterOptionsInput, EventOutput, FeeTransfer, MaxBlockHeightInfo, NetworkStateOutput,
121 TransactionInfo, UserCommand, VerificationKeyUpdate, VerificationKeyUpdateFilterInput,
122 ZkAppCommand,
123};