Expand description
§polyoxide-clob
Rust client library for Polymarket CLOB (Centralized Limit Order Book) API.
§Features
- Order creation, signing, and posting with EIP-712
- Market data and order book retrieval
- Account balance and trade history
- HMAC-based L2 authentication
- Type-safe API with idiomatic Rust patterns
§Example
use polyoxide_clob::{Account, Chain, ClobBuilder, CreateOrderParams, OrderKind, OrderSide};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Load account from environment variables
let account = Account::from_env()?;
// Create CLOB client
let clob = ClobBuilder::new()
.with_account(account)
.chain(Chain::PolygonMainnet)
.build()?;
// Place an order
let params = CreateOrderParams {
token_id: "token_id".to_string(),
price: 0.52,
size: 100.0,
side: OrderSide::Buy,
order_type: OrderKind::Gtc,
post_only: false,
expiration: None,
funder: None,
signature_type: None,
};
let response = clob.place_order(¶ms, None).await?;
println!("Order ID: {:?}", response.order_id);
Ok(())
}§Order outcomes and retries
Polymarket returns HTTP 400 both for genuine faults (malformed payload, banned address, tick-size violation) and for the defined kill outcomes of marketable orders — a FAK that matched nothing, a FOK that could not fill in full. Those two are not failures, so they get their own variants rather than collapsing into a generic validation error:
ClobError::FakUnmatched— nothing on the book matched a Fill-And-Kill orderClobError::FokUnfilled— a Fill-Or-Kill order could not be filled entirely
Both are deterministic: resubmitting the identical order cannot change the answer.
ClobError::is_retriable reports that, and is the intended input to a caller’s
retry policy — so retriability never has to be re-derived from status codes or
from the venue’s prose, which changes without notice.
use polyoxide_clob::ClobError;
fn handle(err: ClobError) {
match err {
// Normal outcomes of a marketable order — report, don't retry, don't alert.
ClobError::FakUnmatched { .. } | ClobError::FokUnfilled { .. } => {}
// Rate limits, timeouts, connection failures, 425, and 5xx.
e if e.is_retriable() => {}
// Deterministic faults: auth, validation, signing.
_ => {}
}
}This crate’s own retry loop only ever retries 429, so a killed order has never
been resent by the SDK itself.
Re-exports§
pub use core::chain::Chain;pub use core::chain::Contracts;pub use account::Account;pub use account::AccountConfig;pub use account::Credentials;pub use account::Signer;pub use account::Wallet;pub use api::account::BalanceAllowanceResponse;pub use api::account::BuilderTrade;pub use api::account::ListBuilderTrades;pub use api::account::ListBuilderTradesResponse;pub use api::account::ListClobTrades;pub use api::account::ListTradesResponse;pub use api::account::MakerOrder;pub use api::account::Trade;pub use api::auth::ApiKeyInfo;pub use api::auth::ApiKeyResponse;pub use api::auth::BuilderApiKeyResponse;pub use api::auth::ClosedOnlyResponse;pub use api::auth::ReadonlyApiKeyResponse;pub use api::auth::ValidateKeyResponse;pub use api::health::Health;pub use api::health::ServerTimeResponse;pub use api::markets::BatchPricesHistoryRequest;pub use api::markets::BatchPricesHistoryResponse;pub use api::markets::BookParams;pub use api::markets::CalculatePriceResponse;pub use api::markets::ClobMarketDetails;pub use api::markets::ClobRewards;pub use api::markets::ClobToken;pub use api::markets::FeeDetails;pub use api::markets::LastTradePriceResponse;pub use api::markets::ListClobMarkets;pub use api::markets::ListMarketsResponse;pub use api::markets::LiveActivityMarket;pub use api::markets::Market;pub use api::markets::MarketByTokenResponse;pub use api::markets::MarketPrice;pub use api::markets::MarketToken;pub use api::markets::MidpointResponse;pub use api::markets::OrderBook;pub use api::markets::OrderLevel;pub use api::markets::PriceHistoryPoint;pub use api::markets::PriceResponse;pub use api::markets::PricesHistoryQuery;pub use api::markets::PricesHistoryResponse;pub use api::markets::SpreadResponse;pub use api::notifications::Notification;pub use api::orders::BatchCancelResponse;pub use api::orders::ListOrders;pub use api::orders::ListOrdersResponse;pub use api::orders::OpenOrder;pub use api::orders::OrderResponse;pub use api::orders::OrderScoringResponse;pub use api::rewards::ListMultiRewardMarkets;pub use api::rewards::ListRewardMarkets;pub use api::rewards::ListUserRewardMarkets;pub use api::rewards::MultiMarketOrderBy;pub use api::rewards::Paginated;pub use api::rewards::PublicRewards;pub use api::rewards::RebatedFees;pub use api::rewards::RewardEarnings;pub use api::rewards::RewardMarket;pub use api::rewards::RewardMarketEarning;pub use api::rewards::RewardMarketRequest;pub use api::rewards::RewardPercentages;pub use api::rewards::RewardTotalEarnings;pub use api::rewards::SortPosition;pub use api::rewards::UserEarningsRequest;pub use api::rewards::UserPercentagesRequest;pub use api::rewards::UserRewardMarketOrderBy;pub use api::rewards::UserTotalEarningsRequest;pub use client::Clob;pub use client::ClobBuilder;pub use client::CreateOrderParams;pub use client::SignedOrderPayload;pub use error::ClobError;pub use types::Order;pub use types::OrderKind;pub use types::OrderSide;pub use types::ParseTickSizeError;pub use types::PartialCreateOrderOptions;pub use types::SignatureType;pub use types::SignedOrder;pub use types::TickSize;