sui_graphql/lib.rs
1//! GraphQL client for the [Sui] blockchain.
2//!
3//! [Sui]: https://sui.io
4//!
5//! This crate provides a typed GraphQL client for Sui's GraphQL API with
6//! automatic BCS deserialization and pagination support.
7//!
8//! # Quick Start
9//!
10//! ```no_run
11//! use sui_graphql::Client;
12//!
13//! #[tokio::main]
14//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
15//! let client = Client::new(Client::MAINNET)?;
16//!
17//! // Chain info
18//! let chain_id = client.chain_identifier().await?;
19//! println!("Chain: {chain_id}");
20//!
21//! // Fetch objects, transactions, checkpoints
22//! let obj = client.get_object("0x5".parse()?).await?;
23//! let tx = client.get_transaction("digest...").await?;
24//! let cp = client.get_checkpoint(None).await?; // latest
25//!
26//! Ok(())
27//! }
28//! ```
29//!
30//! # Streaming
31//!
32//! List methods return async streams with automatic pagination:
33//!
34//! ```no_run
35//! use futures::StreamExt;
36//! use std::pin::pin;
37//! use sui_graphql::Client;
38//! use sui_sdk_types::Address;
39//!
40//! #[tokio::main]
41//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
42//! let client = Client::new(Client::MAINNET)?;
43//! let owner: Address = "0x123...".parse()?;
44//!
45//! let mut stream = pin!(client.list_objects(owner));
46//! while let Some(obj) = stream.next().await {
47//! let obj = obj?;
48//! println!("Object version: {}", obj.version());
49//! }
50//! Ok(())
51//! }
52//! ```
53//!
54//! # Custom Queries
55//!
56//! For queries beyond the built-in methods, use [`Client::query`] with a
57//! response type that implements [`serde::de::DeserializeOwned`]. The
58//! [`sui-graphql-macros`] crate provides `#[derive(Response)]` which generates
59//! the deserialization code from declarative field paths, with compile-time
60//! validation against the Sui GraphQL schema.
61//!
62//! [`sui-graphql-macros`]: https://docs.rs/sui-graphql-macros
63//!
64//! ```no_run
65//! use sui_graphql::Client;
66//! use sui_graphql_macros::Response;
67//!
68//! // Define a response type with field paths into the GraphQL response JSON.
69//! // Paths are validated against the schema at compile time — typos like
70//! // "epoch.epochIdd" will produce a compile error with a "Did you mean?" suggestion.
71//! #[derive(Response)]
72//! struct MyResponse {
73//! #[field(path = "epoch.epochId")]
74//! epoch_id: u64,
75//! // Use `[]` to extract items from a list field
76//! #[field(path = "epoch.checkpoints.nodes[].digest")]
77//! checkpoint_digests: Vec<String>,
78//! // Use `?` to mark nullable fields — null returns Ok(None) instead of an error.
79//! // Without `?`, a null value at that segment is a runtime error.
80//! #[field(path = "epoch.referenceGasPrice?")]
81//! gas_price: Option<u64>,
82//! }
83//!
84//! #[tokio::main]
85//! async fn main() -> Result<(), sui_graphql::Error> {
86//! let client = Client::new(Client::MAINNET)?;
87//!
88//! let query = r#"
89//! query($epoch_id: UInt53) {
90//! epoch(id: $epoch_id) {
91//! epochId
92//! checkpoints { nodes { digest } }
93//! referenceGasPrice
94//! }
95//! }
96//! "#;
97//! let variables = serde_json::json!({ "epoch_id": 100 });
98//!
99//! let response = client.query::<MyResponse>(query, variables).await?;
100//!
101//! // GraphQL supports partial success — data and errors can coexist
102//! for err in response.errors() {
103//! eprintln!("GraphQL error: {}", err.message());
104//! }
105//! if let Some(data) = response.data() {
106//! println!("Epoch: {}", data.epoch_id);
107//! println!("Checkpoints: {:?}", data.checkpoint_digests);
108//! println!("Gas price: {:?}", data.gas_price);
109//! }
110//! Ok(())
111//! }
112//! ```
113//!
114//! For the full path syntax reference (`?`, `[]`, aliases, enums), see the
115//! [`sui-graphql-macros` documentation](https://docs.rs/sui-graphql-macros).
116//!
117//! See [`Client`] for the full list of available methods.
118
119mod bcs;
120mod client;
121mod error;
122mod move_value;
123mod pagination;
124mod response;
125pub mod scalars;
126
127pub use bcs::Bcs;
128pub use bcs::BcsBytes;
129pub use client::Client;
130pub use client::chain::Epoch;
131pub use client::checkpoints::CheckpointResponse;
132pub use client::coins::Balance;
133pub use client::dynamic_fields::DynamicField;
134pub use client::dynamic_fields::DynamicFieldRequest;
135pub use client::dynamic_fields::DynamicFieldValue;
136pub use client::dynamic_fields::DynamicFieldsRequest;
137pub use client::dynamic_fields::Format;
138pub use client::execution::ExecutionResult;
139pub use client::transactions::TransactionResponse;
140pub use error::Error;
141pub use error::GraphQLError;
142pub use error::Location;
143pub use error::PathFragment;
144pub use move_value::MoveObject;
145pub use move_value::MoveValue;
146pub use pagination::Page;
147pub use pagination::PageInfo;
148pub use pagination::paginate;
149pub use pagination::paginate_backward;
150pub use response::Response;