Trading on Openfish
At its core, Openfish runs a Central Limit Order Book (CLOB) tailored for prediction markets. The platform pairs offchain order matching with flexible settlement — you can run against a mock backend during development or settle trades on-chain through the Openfish CTF Exchange contract deployed on Polygon.
Every order is an EIP-712 signed payload sent through the REST API. Inside the server, an in-memory matching engine fills incoming orders against resting liquidity by price-time priority, persists the results, and optionally pushes settlement transactions on-chain.
The official Rust SDK is the simplest way to get started:
- Rust Client — openfish-clob-client:
cargo add openfish-client-sdk --features clob
Alternatively, you can call the REST API directly. In that case, you are responsible for constructing EIP-712 order signatures and attaching HMAC authentication headers to every request.
Two-Tier Authentication
Section titled “Two-Tier Authentication”Openfish separates credential creation from day-to-day API access using two distinct authentication tiers:
| Tier | Mechanism | Role |
|---|---|---|
| L1 | EIP-712 signature (private key) | Create or derive API credentials |
| L2 | HMAC-SHA256 (API credentials) | Place orders, cancel orders, query trades |
You sign a single EIP-712 message with your private key to obtain L2 credentials — an API key, secret, and passphrase. From that point forward, every trading request authenticates through HMAC using those credentials.
Obtaining API Credentials
Section titled “Obtaining API Credentials”use std::str::FromStr;use openfish_client_sdk::POLYGON;use openfish_client_sdk::auth::{LocalSigner, Signer};use openfish_client_sdk::clob::{Client, Config};
let private_key = std::env::var("OPENFISH_PRIVATE_KEY")?;let signer = LocalSigner::from_str(&private_key)? .with_chain_id(Some(POLYGON));
let client = Client::new("https://api.openfish.fun", Config::default())? .authentication_builder(&signer) .authenticate() .await?;L1 Headers (EIP-712)
Section titled “L1 Headers (EIP-712)”These headers are only needed when generating or recovering API credentials:
| Header | Description |
|---|---|
OPENFISH_ADDRESS | Your wallet address |
OPENFISH_SIGNATURE | EIP-712 signature over a ClobAuth struct |
OPENFISH_TIMESTAMP | Unix timestamp |
OPENFISH_NONCE | Request nonce |
The ClobAuth struct signed via EIP-712 contains address, timestamp, nonce, and a fixed attestation message. The domain uses name ClobAuthDomain, version 1, and your chain ID.
L2 Headers (HMAC)
Section titled “L2 Headers (HMAC)”Attached to every trading-related request:
| Header | Description |
|---|---|
OPENFISH_ADDRESS | Your wallet address |
OPENFISH_SIGNATURE | HMAC-SHA256 of {timestamp}{method}{path}{body} |
OPENFISH_TIMESTAMP | Unix timestamp |
OPENFISH_API_KEY | Your API key (UUID) |
OPENFISH_PASSPHRASE | Your API passphrase |
The HMAC secret is base64url-decoded before use. The message format is the concatenation of timestamp, HTTP method, request path, and request body.
How an Order Moves Through the System
Section titled “How an Order Moves Through the System”- Client constructs and signs an EIP-712 order payload — token ID, maker/taker amounts, side, expiration, and fee rate
- Client sends the signed order to
POST /orderalong with L2 authentication headers - Server checks tick size compliance, available balance, and token allowance
- Server writes the order to the database
- Matching engine attempts to fill the order against resting liquidity using price-time priority
- Fills are recorded as trades; balance transfers take effect immediately
- WebSocket broadcasts price changes and fill notifications to subscribers
- Settlement (when running in onchain mode) submits the matched trade to the Exchange contract
Settlement Modes
Section titled “Settlement Modes”The server supports two settlement backends, toggled at startup:
| Mode | Description | Use Case |
|---|---|---|
| Mock | Trades are recorded in the database but not submitted onchain | Development, testing, paper trading |
| Onchain | Trades settle atomically via the CTF Exchange contract on Polygon | Production trading |
Both modes share the same matching engine and order flow. The Settler trait defines the interface, with MockSettler and OnchainSettler as implementations.
In onchain mode, the settlement task reads pending trades from the database, constructs calldata from the signed order data (maker, signer, signature, expiration), and submits the transaction. Trade status progresses through MATCHED -> MINED -> CONFIRMED, or FAILED if the transaction reverts.
Client Methods
Section titled “Client Methods”- Public Methods — Market data, orderbooks, prices — no auth required. -> clients/public
- L1 Methods — Create or derive API credentials with your private key. -> clients/l1
- L2 Methods — Place orders, cancel orders, query trades. -> clients/l2
- Builder Methods — Attributed orders and builder credentials. -> clients/builder
What Is in This Section
Section titled “What Is in This Section”- Quickstart — Place your first order end-to-end -> quickstart
- Fees — Fee structure and the fee rate formula -> fees
- Gasless Transactions — Submit meta-transactions via the relayer -> gasless
- Matching Engine — In-memory matching, restarts, and order restoration -> matching-engine
- Orderbook — Reading prices, spreads, and depth -> orderbook
- Orders — Order types, creating, cancelling, and querying -> orders/overview