mina_sdk/lib.rs
1//! Rust SDK for interacting with [Mina Protocol](https://minaprotocol.com) nodes via GraphQL.
2//!
3//! Mina is a lightweight blockchain (about 22 KB) powered by recursive zero-knowledge proofs.
4//! This crate provides a typed, async client for the Mina daemon's GraphQL API — covering
5//! node status, account queries, block exploration, payments, stake delegation, and SNARK
6//! worker configuration.
7//!
8//! # Features
9//!
10//! - **Async/await** — built on [tokio](https://tokio.rs) and [reqwest](https://docs.rs/reqwest)
11//! - **Typed responses** — every query returns a strongly-typed Rust struct
12//! - **Automatic retry** — configurable retry count and delay for transient failures
13//! - **Currency safety** — [`Currency`] type with nanomina precision and overflow-safe arithmetic
14//! - **Extensible** — [`MinaClient::execute_query`] runs arbitrary GraphQL through the same
15//! retry-aware client; [`queries`] module exposes all built-in query strings
16//! - **Tracing** — all requests are instrumented with [`tracing`](https://docs.rs/tracing)
17//!
18//! # Quick Start
19//!
20//! ```no_run
21//! # async fn example() -> mina_sdk::Result<()> {
22//! use mina_sdk::{MinaClient, Payment, Currency};
23//!
24//! let client = MinaClient::new("http://127.0.0.1:3085/graphql");
25//!
26//! // Query node status
27//! let status = client.get_sync_status().await?;
28//! println!("Node is {status}");
29//!
30//! // Send a payment
31//! let result = client.send_payment(
32//! Payment::sender("B62q..sender..")
33//! .to("B62q..receiver..")
34//! .amount(Currency::from_mina("1.5")?)
35//! .fee(Currency::from_mina("0.01")?)
36//! .memo("hello"),
37//! ).await?;
38//! println!("Payment hash: {}", result.hash);
39//! # Ok(())
40//! # }
41//! ```
42//!
43//! # Custom Configuration
44//!
45//! ```no_run
46//! use mina_sdk::{ClientConfig, MinaClient};
47//! use std::time::Duration;
48//!
49//! let client = MinaClient::with_config(ClientConfig {
50//! graphql_uri: "http://my-node:3085/graphql".to_string(),
51//! retries: 5,
52//! retry_delay: Duration::from_secs(10),
53//! timeout: Duration::from_secs(60),
54//! });
55//! ```
56//!
57//! # Currency
58//!
59//! The [`Currency`] type represents MINA amounts stored internally as nanomina (1 MINA = 10^9
60//! nanomina). It provides safe conversions and arithmetic:
61//!
62//! ```
63//! use mina_sdk::Currency;
64//!
65//! let amount = Currency::from_mina("1.5").unwrap();
66//! assert_eq!(amount.nanomina(), 1_500_000_000);
67//! assert_eq!(amount.mina(), "1.500000000");
68//!
69//! let fee = Currency::from_mina("0.01").unwrap();
70//! let total = amount + fee;
71//! assert_eq!(total, Currency::from_mina("1.51").unwrap());
72//!
73//! // Overflow-safe variants
74//! assert!(fee.checked_add(amount).is_some());
75//! assert!(amount.checked_sub(fee).is_ok());
76//! ```
77//!
78//! # Error Handling
79//!
80//! All fallible operations return [`Result<T>`](Result), which uses [`Error`]. Match on
81//! variants for fine-grained control:
82//!
83//! ```no_run
84//! # async fn example() -> mina_sdk::Result<()> {
85//! use mina_sdk::{MinaClient, Error};
86//!
87//! let client = MinaClient::new("http://127.0.0.1:3085/graphql");
88//! match client.get_account("B62q...", None).await {
89//! Ok(account) => println!("Balance: {}", account.balance.total),
90//! Err(Error::AccountNotFound(key)) => eprintln!("No such account: {key}"),
91//! Err(Error::Connection { attempts, .. }) => eprintln!("Node unreachable after {attempts} tries"),
92//! Err(e) => eprintln!("Error: {e}"),
93//! }
94//! # Ok(())
95//! # }
96//! ```
97//!
98//! # API Overview
99//!
100//! | Method | Description |
101//! |--------|-------------|
102//! | [`MinaClient::get_sync_status`] | Node sync state (Synced, Bootstrap, etc.) |
103//! | [`MinaClient::get_daemon_status`] | Comprehensive daemon info |
104//! | [`MinaClient::get_network_id`] | Network identifier string |
105//! | [`MinaClient::get_account`] | Account balance, nonce, delegate |
106//! | [`MinaClient::get_best_chain`] | Recent blocks from the best chain |
107//! | [`MinaClient::get_peers`] | Connected peer list |
108//! | [`MinaClient::get_pooled_user_commands`] | Pending transaction pool |
109//! | [`MinaClient::send_payment`] | Send a MINA payment |
110//! | [`MinaClient::send_delegation`] | Delegate stake to a validator |
111//! | [`MinaClient::set_snark_worker`] | Enable/disable SNARK worker |
112//! | [`MinaClient::set_snark_work_fee`] | Set SNARK work fee |
113//! | [`MinaClient::execute_query`] | Run arbitrary GraphQL |
114//!
115//! # Examples
116//!
117//! See the [`examples/`](https://github.com/MinaProtocol/mina-sdk-rust/tree/master/examples)
118//! directory for runnable programs:
119//!
120//! - **basic_usage** — connect, query status, browse blocks and accounts
121//! - **send_payment** — submit a payment transaction
122//! - **stake_delegation** — delegate stake to a validator
123//! - **currency_operations** — create, convert, and do arithmetic on amounts (no node needed)
124//! - **custom_query** — run arbitrary GraphQL through `execute_query`
125//! - **error_handling** — match on specific error variants
126//! - **node_monitoring** — health checks, peer listing, block browsing
127
128mod client;
129mod currency;
130pub mod error;
131pub mod queries;
132mod types;
133
134pub use client::{ClientConfig, MinaClient, QueryBuilder};
135pub use currency::Currency;
136pub use error::{Error, Result};
137pub use types::{
138 AccountBalance, AccountData, BlockInfo, DaemonStatus, Delegation, Payment, PeerInfo,
139 PooledUserCommand, SendDelegationResult, SendPaymentResult, SyncStatus,
140};