o2_sdk/lib.rs
1//! O2 Exchange SDK for Rust.
2//!
3//! A production-quality SDK for interacting with the O2 Exchange,
4//! a fully on-chain order book DEX on the Fuel Network.
5//!
6//! # What This SDK Provides
7//!
8//! - High-level workflow client: [`O2Client`]
9//! - Typed REST API access: [`api::O2Api`]
10//! - Typed WebSocket streams: [`TypedStream`]
11//! - Strong domain models for markets, balances, orders, and sessions
12//!
13//! # Quick Start
14//!
15//! ```rust,no_run
16//! use o2_sdk::{O2Client, Network};
17//!
18//! #[tokio::main]
19//! async fn main() -> Result<(), o2_sdk::O2Error> {
20//! let mut client = O2Client::new(Network::Testnet);
21//!
22//! // Generate a wallet
23//! let wallet = client.generate_wallet()?;
24//!
25//! // Setup account (idempotent)
26//! let _account = client.setup_account(&wallet).await?;
27//!
28//! // Fetch markets
29//! let _markets = client.get_markets().await?;
30//!
31//! Ok(())
32//! }
33//! ```
34//!
35//! # Recommended Workflow
36//!
37//! 1. Create an [`O2Client`] with the target [`Network`].
38//! 2. Create or load a wallet.
39//! 3. Run [`O2Client::setup_account`] once at startup.
40//! 4. Create a signed trading session with [`O2Client::create_session`].
41//! 5. Submit typed actions with [`O2Client::create_order`], or compose a batch with
42//! [`O2Client::actions_for`] then send via [`O2Client::batch_actions`].
43//! 6. Stream updates with [`O2Client::stream_depth`] / [`O2Client::stream_orders`] / [`O2Client::stream_nonce`].
44//!
45//! # Common Tasks
46//!
47//! ## Wallet + Account Setup
48//!
49//! ```rust,no_run
50//! use o2_sdk::{Network, O2Client};
51//!
52//! #[tokio::main]
53//! async fn main() -> Result<(), o2_sdk::O2Error> {
54//! let mut client = O2Client::new(Network::Testnet);
55//! let wallet = client.generate_wallet()?;
56//! let account = client.setup_account(&wallet).await?;
57//!
58//! println!("trade account id: {:?}", account.trade_account_id);
59//! Ok(())
60//! }
61//! ```
62//!
63//! ## Market Discovery + Session Creation
64//!
65//! ```rust,no_run
66//! use o2_sdk::{Network, O2Client};
67//!
68//! #[tokio::main]
69//! async fn main() -> Result<(), o2_sdk::O2Error> {
70//! let mut client = O2Client::new(Network::Testnet);
71//! let owner = client.generate_wallet()?;
72//! client.setup_account(&owner).await?;
73//!
74//! let mut session = client.create_session(&owner, &["fuel/usdc"], std::time::Duration::from_secs(7 * 24 * 3600)).await?;
75//! println!("session nonce: {}", session.nonce);
76//! Ok(())
77//! }
78//! ```
79//!
80//! ## Place and Cancel Orders
81//!
82//! ```rust,no_run
83//! use o2_sdk::{Network, O2Client, OrderType, Side};
84//!
85//! #[tokio::main]
86//! async fn main() -> Result<(), o2_sdk::O2Error> {
87//! let mut client = O2Client::new(Network::Testnet);
88//! let owner = client.generate_wallet()?;
89//! client.setup_account(&owner).await?;
90//!
91//! let market = "fuel/usdc";
92//! let mut session = client.create_session(&owner, &[market], std::time::Duration::from_secs(7 * 24 * 3600)).await?;
93//! let market_info = client.get_market(market).await?;
94//! let price = market_info.price("100")?;
95//! let quantity = market_info.quantity("2")?;
96//!
97//! let response = client
98//! .create_order(
99//! &mut session,
100//! market,
101//! Side::Buy,
102//! price,
103//! quantity,
104//! OrderType::Market,
105//! false,
106//! true,
107//! )
108//! .await?;
109//!
110//! if let Some(order_id) = response
111//! .orders
112//! .as_ref()
113//! .and_then(|orders| orders.first())
114//! .map(|o| o.order_id.clone())
115//! {
116//! let _ = client.cancel_order(&mut session, &order_id, market).await?;
117//! }
118//! Ok(())
119//! }
120//! ```
121//!
122//! ## Balances and Nonce Management
123//!
124//! ```rust,no_run
125//! use o2_sdk::{Network, O2Client};
126//!
127//! #[tokio::main]
128//! async fn main() -> Result<(), o2_sdk::O2Error> {
129//! let mut client = O2Client::new(Network::Testnet);
130//! let wallet = client.generate_wallet()?;
131//! let account = client.setup_account(&wallet).await?;
132//! let trade_account_id = account.trade_account_id.unwrap();
133//!
134//! let balances = client.get_balances(&trade_account_id).await?;
135//! for (symbol, balance) in balances {
136//! println!("{symbol}: {}", balance.trading_account_balance);
137//! }
138//!
139//! let nonce = client.get_nonce(trade_account_id.as_str()).await?;
140//! println!("nonce: {nonce}");
141//! Ok(())
142//! }
143//! ```
144//!
145//! # Logging
146//!
147//! This crate emits debug-level logs through the [`log`](https://docs.rs/log/) facade
148//! for API and client calls. Configure any compatible logger in your binary, then set
149//! `RUST_LOG=debug` to inspect request flow and setup behavior.
150//!
151//! Market metadata refresh can be configured via [`MetadataPolicy`] and
152//! [`O2Client::set_metadata_policy`].
153//!
154//! # Errors
155//!
156//! All fallible operations return [`O2Error`]. Match specific variants for robust handling:
157//!
158//! - Preflight/API validation failures (`code`/`message` style errors)
159//! - On-chain revert failures (`OnChainRevert`)
160//! - Transport/serialization failures (`HttpError`, `JsonError`, etc.)
161//!
162//! See [`guides::error_handling`] for recovery patterns.
163//!
164//! # Guides
165//!
166//! The [`guides`] module contains integration guides covering common
167//! workflows and patterns:
168//!
169//! - [`guides::trading`] — Order types, batch actions, and market maker patterns
170//! - [`guides::market_data`] — Fetching depth, trades, candles, and balances
171//! - [`guides::websocket_streams`] — Real-time data with `TypedStream`
172//! - [`guides::error_handling`] — Error types and recovery patterns
173//! - [`guides::external_signers`] — Integrating KMS/HSM via the `SignableWallet` trait
174pub mod api;
175pub mod client;
176pub mod config;
177pub mod crypto;
178pub mod decimal;
179pub mod encoding;
180pub mod errors;
181pub mod guides;
182pub mod models;
183mod onchain_revert;
184pub mod websocket;
185
186// Re-export primary types for convenience.
187pub use client::{MarketActionsBuilder, MetadataPolicy, O2Client};
188pub use config::{Network, NetworkConfig};
189pub use crypto::{EvmWallet, SignableWallet, Wallet};
190pub use decimal::UnsignedDecimal;
191pub use errors::O2Error;
192pub use models::*;
193pub use models::{
194 Action, AssetId, MarketId, MarketSymbol, OrderId, OrderType, Side, TradeAccountId,
195};
196pub use websocket::{DepthPrecision, O2WebSocket, TypedStream, WsConfig, WsLifecycleEvent};