wf_market/
lib.rs

1//! # wf-market
2//!
3//! A Rust client library for the [warframe.market](https://warframe.market) API.
4//!
5//! This library provides a type-safe, async client for interacting with the
6//! warframe.market trading platform, including both HTTP REST API and WebSocket
7//! real-time updates.
8//!
9//! ## Features
10//!
11//! - **Type-safe API**: Compile-time guarantees prevent common mistakes
12//! - **Async/await**: Built on Tokio for efficient async operations
13//! - **Session persistence**: Save and restore login sessions
14//! - **Rate limiting**: Built-in rate limiter to prevent API throttling
15//! - **Caching**: Optional caching for slowly-changing data
16//! - **WebSocket support**: Real-time updates (optional feature)
17//!
18//! ## Quick Start
19//!
20//! ```ignore
21//! use wf_market::{Client, Credentials, CreateOrder};
22//!
23//! #[tokio::main]
24//! async fn main() -> wf_market::Result<()> {
25//!     // Create a client (fetches items automatically)
26//!     let client = Client::builder().build().await?;
27//!     
28//!     // Items are pre-loaded and accessible via client.items()
29//!     println!("Loaded {} items", client.items().len());
30//!     
31//!     // Get orders for an item
32//!     let orders = client.get_orders("nikana_prime_set").await?;
33//!     for order in orders.iter().take(5) {
34//!         // Item info is automatically available on orders
35//!         if let Some(item) = order.get_item() {
36//!             println!("{}: {} @ {}p", order.user.ingame_name, item.name(), order.platinum);
37//!         }
38//!     }
39//!     
40//!     // Login for authenticated operations
41//!     let creds = Credentials::new(
42//!         "your@email.com",
43//!         "password",
44//!         Credentials::generate_device_id(),
45//!     );
46//!     let client = client.login(creds).await?;
47//!     
48//!     // Create an order
49//!     let order = client.create_order(
50//!         CreateOrder::sell("nikana_prime_set", 100, 1)
51//!     ).await?;
52//!     println!("Created order: {}", order.id());
53//!     
54//!     Ok(())
55//! }
56//! ```
57//!
58//! ## Session Persistence
59//!
60//! Save and restore login sessions to avoid re-authenticating:
61//!
62//! ```ignore
63//! use wf_market::{Client, Credentials};
64//!
65//! async fn example() -> wf_market::Result<()> {
66//!     // Initial login
67//!     let creds = Credentials::new("email", "password", Credentials::generate_device_id());
68//!     let client = Client::from_credentials(creds).await?;
69//!     
70//!     // Save session
71//!     let session = client.export_session();
72//!     let json = serde_json::to_string(&session)?;
73//!     std::fs::write("session.json", &json)?;
74//!     
75//!     // Later: restore session
76//!     let saved: Credentials = serde_json::from_str(&std::fs::read_to_string("session.json")?)?;
77//!     
78//!     // Validate before using (recommended)
79//!     if Client::validate_credentials(&saved).await? {
80//!         let client = Client::from_credentials(saved).await?;
81//!     }
82//!     
83//!     Ok(())
84//! }
85//! ```
86//!
87//! ## Caching
88//!
89//! Use the [`ApiCache`] to persist items across application restarts:
90//!
91//! ```ignore
92//! use wf_market::{Client, ApiCache, SerializableCache};
93//!
94//! async fn example() -> wf_market::Result<()> {
95//!     // Load cache from disk (or create new)
96//!     let mut cache = match std::fs::read_to_string("cache.json") {
97//!         Ok(json) => serde_json::from_str::<SerializableCache>(&json)?
98//!             .into_api_cache(),
99//!         Err(_) => ApiCache::new(),
100//!     };
101//!     
102//!     // Build client using cache (uses cached items if < 1 day old)
103//!     let client = Client::builder()
104//!         .build_with_cache(&mut cache)
105//!         .await?;
106//!     
107//!     // Items are loaded from cache or API
108//!     println!("Loaded {} items", client.items().len());
109//!     
110//!     // Save cache for next time
111//!     let serializable = SerializableCache::from(&cache);
112//!     std::fs::write("cache.json", serde_json::to_string(&serializable)?)?;
113//!     
114//!     Ok(())
115//! }
116//! ```
117//!
118//! ## WebSocket (Real-time Updates)
119//!
120//! Enable the `websocket` feature for real-time order updates:
121//!
122//! ```toml
123//! [dependencies]
124//! wf-market = { version = "0.2", features = ["websocket"] }
125//! ```
126//!
127//! ```ignore
128//! use wf_market::{Client, Credentials};
129//! use wf_market::ws::{WsEvent, Subscription};
130//!
131//! async fn example() -> wf_market::Result<()> {
132//!     let client = Client::from_credentials(/* ... */).await?;
133//!     
134//!     let ws = client.websocket()
135//!         .on_event(|event| async move {
136//!             match event {
137//!                 WsEvent::OnlineCount { authorized, .. } => {
138//!                     println!("Users online: {}", authorized);
139//!                 }
140//!                 WsEvent::OrderCreated { order } => {
141//!                     println!("New order: {}p", order.platinum);
142//!                 }
143//!                 _ => {}
144//!             }
145//!         })
146//!         .subscribe(Subscription::all_new_orders())
147//!         .connect()
148//!         .await?;
149//!     
150//!     Ok(())
151//! }
152//! ```
153//!
154//! ## Feature Flags
155//!
156//! - `default` = `["rustls-tls"]`
157//! - `rustls-tls`: Use rustls for TLS (default)
158//! - `native-tls`: Use native TLS instead of rustls
159//! - `websocket`: Enable WebSocket support for real-time updates
160//! - `v1-api`: Enable deprecated V1 API endpoints (statistics)
161
162// Modules
163mod api;
164pub mod cache;
165pub mod client;
166pub mod error;
167mod internal;
168pub mod models;
169
170#[cfg(feature = "websocket")]
171pub mod ws;
172
173// Re-exports for convenience
174pub use cache::{ApiCache, CachedItems, CachedRivens, SerializableCache};
175pub use client::{AuthState, Authenticated, Client, ClientBuilder, ClientConfig, Unauthenticated};
176pub use error::{ApiErrorDetails, ApiErrorResponse, Error, Result};
177
178#[cfg(feature = "websocket")]
179pub use error::WsError;
180
181// Model re-exports
182pub use models::{
183    // Users
184    Achievement,
185    AchievementType,
186    // Common types
187    Activity,
188    ActivityType,
189    // Orders
190    CreateOrder,
191    // Auth
192    Credentials,
193    FullUser,
194    // Items
195    Item,
196    ItemIndex,
197    ItemSet,
198    ItemTranslation,
199    Language,
200    ModView,
201    Order,
202    OrderListing,
203    OrderType,
204    OwnedOrder,
205    OwnedOrderId,
206    Platform,
207    Rarity,
208    // Rivens
209    Riven,
210    RivenAttribute,
211    RivenAttributeTranslation,
212    RivenTranslation,
213    RivenType,
214    SculptureView,
215    SubscriptionTier,
216    Theme,
217    TopOrderFilters,
218    TopOrders,
219    // Transactions
220    Transaction,
221    UpdateOrder,
222    UpdateProfile,
223    User,
224    UserPrivate,
225    UserProfile,
226    UserRole,
227    UserStatus,
228    WithPassword,
229};
230
231// V1 API model re-exports (deprecated, feature-gated)
232#[cfg(feature = "v1-api")]
233pub use models::{ItemStatistics, StatisticEntry, TimeframedStatistics};