Skip to main content

polymarket_us/
lib.rs

1//! Unofficial Rust SDK for the Polymarket US Retail API.
2//!
3//! The crate exposes a typed async REST client and a managed WebSocket stream.
4//! Requests to authenticated endpoints are signed with Ed25519 and carry the
5//! `X-PM-*` headers automatically.
6//!
7//! # Getting started
8//!
9//! Public endpoints need no credentials:
10//!
11//! ```no_run
12//! use polymarket_us::PolymarketUsClient;
13//!
14//! # async fn run() -> Result<(), polymarket_us::PolymarketUsError> {
15//! let client = PolymarketUsClient::builder().build()?;
16//! let markets = client.markets().list().await?;
17//! println!("{} markets", markets.markets.len());
18//! # Ok(())
19//! # }
20//! ```
21//!
22//! Authenticated endpoints read credentials from `POLYMARKET_US_KEY_ID` and
23//! `POLYMARKET_US_SECRET_KEY`:
24//!
25//! ```no_run
26//! use polymarket_us::{PolymarketUsClient, UsAuth};
27//!
28//! # async fn run() -> Result<(), polymarket_us::PolymarketUsError> {
29//! let client = PolymarketUsClient::builder()
30//!     .auth(UsAuth::from_env()?)
31//!     .build()?;
32//!
33//! let balances = client.account().balances().await?;
34//! # Ok(())
35//! # }
36//! ```
37//!
38//! # Resources
39//!
40//! Endpoints are grouped behind accessors on the client: [`PolymarketUsClient::markets`],
41//! [`PolymarketUsClient::events`], [`PolymarketUsClient::orders`],
42//! [`PolymarketUsClient::account`], [`PolymarketUsClient::portfolio`], and
43//! [`PolymarketUsClient::search`].
44//!
45//! # Retries
46//!
47//! Idempotent requests (`GET`, `DELETE`) are retried with exponential backoff and
48//! jitter, honouring a server-supplied `Retry-After`. `POST` is **never** retried
49//! automatically, so a submitted order cannot be duplicated by the transport
50//! layer. See [`RetryConfig`].
51//!
52//! # Streaming
53//!
54//! [`PolymarketUsStreamClient`] maintains a WebSocket with automatic reconnect,
55//! re-subscribing on every reconnect. Connections that go silent are torn down
56//! after [`StreamConnectConfig::idle_timeout`] so a dead socket cannot stall the
57//! stream indefinitely.
58//!
59//! ```no_run
60//! use polymarket_us::{PolymarketUsStreamClient, StreamSubscription};
61//!
62//! # async fn run() -> Result<(), polymarket_us::PolymarketUsError> {
63//! let stream = PolymarketUsStreamClient::from_gateway_base_url(
64//!     "https://gateway.polymarket.us",
65//!     None,
66//! );
67//!
68//! let mut managed = stream
69//!     .connect(vec![StreamSubscription::market_data("BTC-USD")])
70//!     .await?;
71//!
72//! while let Some(message) = managed.next().await {
73//!     println!("{:?}", message.kind);
74//! }
75//! # Ok(())
76//! # }
77//! ```
78
79pub mod auth;
80pub mod client;
81pub mod error;
82pub mod resources;
83pub mod retry;
84pub mod stream;
85pub mod types;
86
87pub use auth::UsAuth;
88pub use client::{PolymarketUsClient, PolymarketUsClientBuilder};
89pub use error::PolymarketUsError;
90pub use resources::{
91    AccountClient, EventsClient, MarketsClient, OrdersClient, PortfolioClient, SearchClient,
92};
93pub use retry::RetryConfig;
94pub use stream::{
95    ManagedStream, PolymarketUsStreamClient, ReconnectConfig, StreamConnectConfig,
96    StreamControlEvent, StreamDataEvent, StreamMessage, StreamMessageKind, StreamSubscription,
97    SubscriptionChannel,
98};
99pub use types::{MarketStatus, OrderAction, OrderSide, OrderType, TimeInForce};