# GoDark Documentation — Full Text > GoDark is an institutional-grade dark pool DEX for perpetual futures on Solana. Orders match in a central limit order book run across an MPC committee, so no single operator holds the book, and settlement lands on Solana as encrypted commitments. Source: https://docs.godarkdex.com Generated: 2026-08-07 Pages: 46 Some architecture figures are rendered as interactive components on the site and appear here as captions only. ================================================================================ Source: https://docs.godarkdex.com/docs/overview/ # Overview GoDark is a dark pool for perpetual futures on Solana. The orderbook is a **central limit order book (CLOB)** matched with **price–time priority**. The book and matching engine run across an MPC committee, so no single operator holds the book. A sequencer inside a TEE enclave assigns a global order to encrypted payloads before they reach matching. Settlement lands on Solana as encrypted commitments, not readable balances — positions, amounts, and counterparties stay private during and after each trade. ## The GoDark Network ![GoDark High-Level Architecture](https://docs.godarkdex.com/images/architecture/client-high-level-architecture.png) ![Three trust sectors](https://docs.godarkdex.com/images/architecture/trust-sectors-three-columns.png) ## Performance | Metric | Value | |---|---| | Matching latency | ~150–750μs per order | | Throughput | 10,000+ orders/second | | Fault tolerance | Any 2 of 5 nodes can fail without downtime | | Geographic resilience | Automatic failover across 3–4 global regions in ~20–50ms | These numbers reflect the MPC protocol's overhead relative to a centralized engine. Sub-millisecond matching is more than sufficient for the target use case: traders who value privacy and execution quality over raw speed. ================================================================================ Source: https://docs.godarkdex.com/docs/connect-wallet/ # Connect Wallet ![Getting started tutorial](https://docs.godarkdex.com/embeds/getting-started-tutorial) GoDark DEX uses wallet-based identity. All wallets are created via [Fireblocks](https://www.fireblocks.com/) embedded wallets. Funding from external wallets (e.g. Phantom, Solflare, Trust Wallet) is supported. ## How It Works | Step | Description | |------|-------------| | **Sign up** | Create an account with your email address. A new embedded Solana wallet is provisioned for you via [Fireblocks](https://www.fireblocks.com/). | | **Identity** | Your wallet address becomes your account identifier — it is the `userId` for API calls and the destination for deposits. Ghost withdrawals release funds to fresh ephemeral recipient addresses designed to reduce public linkability to your wallet. | Not every user starts in the app: - **Building on the API** — jump to [Authentication](https://docs.godarkdex.com/docs/authentication), [Base URLs](https://docs.godarkdex.com/docs/base-urls), and [Place Your First Order](https://docs.godarkdex.com/docs/place-order). See the [SDKs](https://docs.godarkdex.com/docs/sdks) section for Python, Rust, JavaScript/TypeScript, C++, Go, and Java clients. - **Auditing the design** — read [Trade Flow](https://docs.godarkdex.com/docs/trade-flow), [MPC Architecture](https://docs.godarkdex.com/docs/mpc-architecture), and [Settlement](https://docs.godarkdex.com/docs/settlement). ================================================================================ Source: https://docs.godarkdex.com/docs/deposit-funds/ # Deposit Funds After creating your [Dynamic wallet](https://www.dynamic.xyz/), deposit collateral to start trading. Deposited USDC is automatically shielded for private trading (see [Shielded Pool](https://docs.godarkdex.com/docs/shielded-pool) and [Settlement](https://docs.godarkdex.com/docs/settlement)). On **testnet**, deposit funds using the [GoDark Testnet Faucet](https://faucet.godark-dex.com/). ## Deposit Methods ### Crypto Deposits Send USDC (SPL token on Solana) directly to your Dynamic wallet address: 1. In the app, open the **Deposit** modal and copy your Dynamic wallet address (or scan the QR code) 2. From your external wallet or exchange, send USDC on the **Solana network** to that address 3. Confirm the transaction. Funds typically arrive within 1 minute (Solana block confirmation) 4. USDC is credited to your account, automatically shielded, and available for trading Use the Solana network only — sending USDC on other chains (Ethereum, etc.) will not credit your account. ### Fiat Deposits #### Topper (Card / Mobile Pay) Use credit card, debit card, Apple Pay, or Google Pay to buy USDC. Available in the app via the Deposit modal. USDC is sent directly to your Dynamic wallet and automatically shielded. Limits and processing times vary by region. #### Wire / ACH / SEPA (Bridge) Bank transfer (USD, EUR) for larger deposits. | Method | Region | Processing Time | |--------|--------|-----------------| | ACH | US | 1–3 business days | | Wire | US | Same-day when submitted before cutoff | | SEPA | Europe | Typically 1 business day | Funds are converted to USDC, credited to your Dynamic wallet, and automatically shielded. ## Where Your Deposit Lives When USDC lands in your [Dynamic wallet](https://www.dynamic.xyz/), GoDark automatically shields it for trading. The visible deposit becomes a private commitment inside GoDark's shielded pool, so the trading layer can work with collateral without exposing per-user balances on-chain. - **Dynamic wallet.** This is your user-facing wallet and account identity. Deposits arrive here first. - **Shielded pool.** GoDark moves deposited collateral behind a private commitment tree. The public chain can verify pool solvency without revealing your individual balance, position, or counterparty. - **Trading.** The engine operates on private commitments only. Individual trades do not publish readable amounts or per-user balance changes. - **Withdraw.** Withdrawing proves ownership of your private commitment and releases collateral to a fresh ephemeral recipient address designed to reduce the public link back to your Dynamic wallet. See [Settlement](https://docs.godarkdex.com/docs/settlement) for the full flow. The only on-chain quantity anyone can read is the shielded pool's aggregate total — per-user amounts, positions, and counterparties stay private behind the commitment tree. For the full custody, visibility, and solvency model, see [Shielded Pool](https://docs.godarkdex.com/docs/shielded-pool). ================================================================================ Source: https://docs.godarkdex.com/docs/trading-interface/ # Trading Interface The GoDark web application at [app.godark-dex.com](https://app.godark-dex.com) is the primary interface for placing and managing trades. This page describes the trading UI — layout modes, order entry panels, and market data views. For programmatic access, see [Programmatic Access](https://docs.godarkdex.com/docs/programmatic-access). ## Layout Modes On desktop, you can choose from three resizable layouts. Your selection is saved in the browser and restored on your next visit. **Balanced** is the default. | Layout | What you see | | --- | --- | | **Basic** | Chart and working orders in the main area; a simplified order panel on the right. No reference order book or trades. | | **Balanced** | Order entry and account metrics on the left; reference order book or trades beside the chart; working orders below. | | **Pro** | Chart with reference order book and trades visible at the same time; order panel and account metrics on the right; working orders below. | To change layout, use the **Layout** control in the header. Each option shows a small preview of the panel arrangement. Layout modes are available on desktop only — see [Responsive Layouts](#responsive-layouts) for mobile and tablet. ## Order Entry Panels Layout choice controls where panels appear, not which features are available. Two order panels are used: | Panel | Used in | Order types | | --- | --- | --- | | **Simple** | Basic layout; mobile and tablet | Swap, Market, Limit | | **Full** | Balanced and Pro layouts | Market, Limit | ### Simple Order Panel - **Leverage:** 1×–10× via slider and numeric input - **Take profit / stop loss:** Optional price inputs - **Time in force:** GTC, IOC, FOK ### Full Order Panel - **Leverage:** 1×–10× via a leverage dialog (slider and numeric input) - **Take profit / stop loss:** Price and gain/loss fields in $ or % - **Time in force:** GTC, IOC, FOK, and GTD (UTC date/time picker) - **Execution attributes:** All/None and Min Fill - **Peg orders:** Shown in the menu but not yet available in the web UI All desktop layouts include a **Working orders** table with real-time fill updates below the chart. ## Chart and Reference Data | Component | Source | | --- | --- | | **Price chart** | TradingView Advanced Chart, fed by Pyth oracle data. Indicators such as MA, EMA, Bollinger Bands, RSI, MACD, and VWAP are available through the chart widget. | | **Reference order book** | Aggregated depth from Hyperliquid and Binance. You can choose which venues to display. | | **Reference trades** | Recent trades from Hyperliquid and Binance. You can choose which venues to display. | | **Mark / oracle price** | Pyth (primary) and Switchboard (failover), selectable in the order panel | Reference order book and trades show activity from other venues for comparison. They do not represent GoDark's internal order book. ## Margin Health The web UI displays a **margin health bar** and tier banners that mirror the sequencer's six-band margin ladder (Healthy through T3). Colors and thresholds match the backend liquidation monitor. See [Margin & Liquidation](https://docs.godarkdex.com/docs/margin-and-liquidation#margin-health-tiers) for tier definitions and what happens at each level. ## Responsive Layouts On mobile and tablet, layout modes are not used. The interface switches to tabs and always uses the simple order panel. | Viewport | Navigation | Order panel | | --- | --- | --- | | **Mobile** | Trade, Chart, Order book, Account, Positions | Simple | | **Tablet** | Chart and working orders on the left; order panel on the right | Simple | On mobile, the Order book tab switches between reference order book and reference trades. ## See Also - [Order Types](https://docs.godarkdex.com/docs/order-types) — market, limit, and peg order semantics - [Time in Force](https://docs.godarkdex.com/docs/time-in-force) — GTC, GTT, IOC, and FOK (the web UI labels timed expiry as GTD) - [Execution Attributes](https://docs.godarkdex.com/docs/execution-attributes) — All/None and minimum fill size - [Pegged Orders](https://docs.godarkdex.com/docs/pegged-orders) — peg order support via the API - [Margin & Liquidation](https://docs.godarkdex.com/docs/margin-and-liquidation) — margin health tiers and liquidation ladder ================================================================================ Source: https://docs.godarkdex.com/docs/programmatic-access/ # Programmatic Access For bots, algo trading, or other integrations, use the REST and WebSocket APIs described in this documentation. ## Authentication Model - **Trading endpoints** (orders, positions, mass quote) require a short-lived Bearer token (see [Authentication](https://docs.godarkdex.com/docs/authentication)) - **Public endpoints** (instruments, transparency, VIP tier schedule) require no account token - **WebSocket trading** authenticates via `login` with a Bearer token; optional encrypted session framing is described in [Encryption & Transport](https://docs.godarkdex.com/docs/encryption) ## Available APIs | Interface | Protocol | Use Case | |-----------|----------|----------| | **REST** | HTTPS | Auth, orders, mass quote (Prime/Apex), positions, stats, tiers, referrals, settlement status, instruments, market data proxies | | **WebSocket** | WSS | Order updates (`/ws/orders`), order submission (`/ws/trading`), user events (`/ws/user`), external venue data (`/ws/gomarket`) | | **SSE** | HTTP | Real-time stats (`/events/stats`), notifications (`/events/notifications`) | ## Quick Start 1. **Get your wallet address** — This is your `userId` for all API calls 2. **Obtain handshake token** — For WebSocket connections (provided during onboarding) 3. **Place your first order** — See [Place Order](https://docs.godarkdex.com/docs/place-order) 4. **Subscribe to updates** — Connect to [Order Updates](https://docs.godarkdex.com/docs/order-updates) Market makers on Prime/Apex tiers can use [Mass Quote](https://docs.godarkdex.com/docs/mass-quote) for batch cancel-replace. See [System Status](https://docs.godarkdex.com/docs/system-status) for degraded mode (`202` / `1502`) behavior. ## SDKs Official client libraries for REST and WebSocket trading: - [SDK overview](https://docs.godarkdex.com/docs/sdks) - [Python SDK](https://docs.godarkdex.com/docs/sdks/python) - [Rust SDK](https://docs.godarkdex.com/docs/sdks/rust) - [JavaScript / TypeScript SDK](https://docs.godarkdex.com/docs/sdks/javascript) - [C++ SDK](https://docs.godarkdex.com/docs/sdks/cpp) - [Go SDK](https://docs.godarkdex.com/docs/sdks/go) - [Java SDK](https://docs.godarkdex.com/docs/sdks/java) ## Rate Limits Different tiers have different rate limits. See [Rate Limits](https://docs.godarkdex.com/docs/rate-limits) for details. ================================================================================ Source: https://docs.godarkdex.com/docs/authentication/ # Authentication All GoDark API endpoints use a single authentication model: long-lived `api_key` + `api_secret` + `passphrase` credentials are exchanged for a short-lived bearer token via OAuth 2.0 `client_credentials`. ## Credential Model | Layer | Credential | Lifetime | Purpose | | --- | --- | --- | --- | | Long-lived | `api_key` + `api_secret` + `passphrase` | Until rotated | Identify your account. The `passphrase` is set by you at key-creation time and must be supplied with every token exchange — it is not recoverable if lost. | | Short-lived | `access_token` (JWT Bearer) | 15 minutes | Sent with every REST request and on WebSocket `login`. | Generate and manage `api_key` / `api_secret` / `passphrase` triples from the app under **Settings → API Keys**. The passphrase is shown once at creation time; if you lose it, rotate the key. ## POST /auth/token Exchange credentials for a bearer token. RFC 6749 `client_credentials` grant. ``` POST /api/v1/auth/token ``` ### Request ```http Content-Type: application/json ``` ```json { "grant_type": "client_credentials", "client_id": "", "client_secret": "", "passphrase": "" } ``` ### Response ```json { "access_token": "eyJhbGciOi...", "token_type": "Bearer", "expires_in": 900, "scope": "trade read" } ``` | Field | Description | | --- | --- | | `access_token` | Short-lived JWT bearer token. | | `token_type` | Always `Bearer`. | | `expires_in` | Token lifetime in seconds (default `900` = 15 min). | | `scope` | Space-separated list of granted scopes (`trade`, `read`). | ### cURL ```bash curl -X POST https://api.godarkdex.com/api/v1/auth/token \ -H "Content-Type: application/json" \ -d '{ "grant_type": "client_credentials", "client_id": "YOUR_API_KEY", "client_secret": "YOUR_API_SECRET", "passphrase": "YOUR_PASSPHRASE" }' ``` ## POST /auth/token/revoke Invalidate an access token before its natural expiry. RFC 7009. ``` POST /api/v1/auth/token/revoke ``` ### Request ```json { "token": "eyJhbGciOi..." } ``` ### Response `204 No Content` on success. Revoking an already-expired or unknown token is a no-op and also returns `204`. ## Using the Bearer Token Every subsequent REST request must include: ```http Authorization: Bearer ``` For WebSocket, authenticate the socket with an `op: "login"` frame carrying the same token — see [WebSocket Trading](https://docs.godarkdex.com/docs/ws-trading). ## Token Expiry Access tokens expire after 15 minutes. On expiry: - REST: the next request returns `401 token_expired`. Call `POST /auth/token` again. - WebSocket: the server emits an `auth_expired` event ~60 seconds before expiry. Send a fresh `op: "login"` with a new token to continue on the same socket without dropping subscriptions. ## Public (Unauthenticated) Endpoints The following endpoints do not require a bearer token: - `POST /auth/token`, `POST /auth/token/revoke` - `GET /instruments`, `GET /instruments/{symbol}` - `GET /vip/tiers` - `GET /transparency` All other endpoints require `Authorization: Bearer `. ## Errors | Status | Code | Meaning | | --- | --- | --- | | `400` | `invalid_request` | Malformed request (missing `grant_type`, `passphrase`, bad JSON). | | `400` | `unsupported_grant_type` | Only `client_credentials` is supported. | | `401` | `invalid_client` | Unknown `client_id`, bad `client_secret`, or bad `passphrase`. | | `401` | `token_expired` | Bearer token is past its `expires_in` window. | | `401` | `token_revoked` | Token was revoked via `/auth/token/revoke`. | | `403` | `insufficient_scope` | Token lacks the required scope for the endpoint. | See [Error Codes](https://docs.godarkdex.com/docs/error-codes) for the full reference. --- ================================================================================ Source: https://docs.godarkdex.com/docs/base-urls/ # Base URLs All REST endpoints live under a single versioned gateway. All WebSocket traffic runs on a single multiplexed socket. ## Gateway ### Mainnet | Transport | Base URL | | --- | --- | | REST | `https://api.godarkdex.com/api/v1` | | WebSocket | `wss://api.godarkdex.com/ws/v1` | ### Testnet | Transport | Base URL | | --- | --- | | REST | `https://api.godarkdex-testnet.com/api/v1` | | WebSocket | `wss://api.godarkdex-testnet.com/ws/v1` | API keys, bearer tokens, and balances are not shared between mainnet and testnet — credentials issued on one environment will not authenticate against the other. All REST examples in these docs omit the base URL for brevity and default to mainnet. A request shown as `POST /orders` means `POST https://api.godarkdex.com/api/v1/orders` on mainnet or `POST https://api.godarkdex-testnet.com/api/v1/orders` on testnet. ## Endpoint Reference ### REST | Method | Path | Auth | Purpose | | --- | --- | --- | --- | | `POST` | `/auth/token` | — | Exchange `api_key` + `api_secret` + `passphrase` for bearer token | | `POST` | `/auth/token/revoke` | — | Revoke a bearer token | | `GET` | `/instruments` | — | List all tradable instruments | | `GET` | `/instruments/{symbol}` | — | Single instrument detail | | `POST` | `/orders` | Bearer | Place an order | | `DELETE` | `/orders/{orderId}` | Bearer | Cancel an order | | `PATCH` | `/orders/{orderId}` | Bearer | Modify an order | | `GET` | `/orders/{orderId}` | Bearer | Fetch a single order by id | | `POST` | `/orders/mass-quote` | Bearer | Batch cancel-replace (Prime and Apex tiers) | | `GET` | `/positions` | Bearer | Snapshot of open positions | | `GET` | `/account` | Bearer | Balance, VIP tier, and account-level config in one call | | `GET` | `/account/vip` | Bearer | Current VIP tier and rolling 30d volume | | `GET` | `/vip/tiers` | — | Public fee schedule for all tiers | | `GET` | `/transparency` | — | Single public transparency snapshot: reserves root, engine attestation, and aggregate stats (supports `?epoch=` and `?window=`) | | `GET` | `/settlement/status/{batchId}` | Bearer | Batch settlement status | ### WebSocket One endpoint, one socket per session. Ops and channels are multiplexed: ``` wss://api.godarkdex.com/ws/v1 ``` | Op / Channel | Direction | Purpose | | --- | --- | --- | | `op: login` | Client → Server | Authenticate the socket using a bearer token | | `op: logout` | Client → Server | End the session cleanly | | `op: ping` / `pong` | Both | Heartbeat | | `op: subscribe` / `unsubscribe` | Client → Server | Manage channel subscriptions | | `op: account.info` | Client → Server | Fetch balance, VIP tier, and account config (mirrors `GET /account`) | | `op: order.place` / `order.cancel` / `order.modify` | Client → Server | Trading (mirrors REST) | | `channel: orders` | Server → Client | Snapshot + incremental order updates | | `channel: positions` | Server → Client | Snapshot + incremental position updates | See [WebSocket Trading](https://docs.godarkdex.com/docs/ws-trading), [Orders Channel](https://docs.godarkdex.com/docs/order-updates), and [Positions Channel](https://docs.godarkdex.com/docs/ws-user-events) for message schemas. ## Common Headers All authenticated REST requests require: ```http Content-Type: application/json Authorization: Bearer ``` All responses include: | Header | Purpose | | --- | --- | | `X-Request-Id` | Unique id for this request. Echo in bug reports. | | `X-RateLimit-Limit` | Request budget for the current window. | | `X-RateLimit-Remaining` | Requests left in the current window. | | `X-RateLimit-Reset` | Unix seconds when the window resets. | ## Response format All REST responses share the same JSON shape: ```json { "code": 0, "data": { }, "timestamp": "2026-04-20T10:30:00.123Z", "request_id": "req_01HXYZ..." } ``` On error: ```json { "code": 1410, "message": "Margin insufficient", "timestamp": "2026-04-20T10:30:00.123Z", "request_id": "req_01HXYZ..." } ``` See [Error Codes](https://docs.godarkdex.com/docs/error-codes) for the code reference. ## Server Time ``` GET /time ``` Returns server time (useful for clock-skew diagnostics and signing windows). ```json { "code": 0, "data": { "server_time": "2026-04-20T10:30:00.123Z", "server_time_ns": 1839975000123000000 } } ``` --- ================================================================================ Source: https://docs.godarkdex.com/docs/encryption/ # Encryption & Transport Trading requests to GoDark are end-to-end encrypted on the WebSocket channel. The bodies the rest of the docs describe — `order.place`, `order.cancel`, `order.modify` — are the **logical** requests. Actual wire bytes are AES-256-GCM ciphertext produced by an ephemeral session key negotiated with the gateway. This page specifies that channel: the handshake, the key derivation, the framing, and the authenticated envelope. It exists so auditors and people porting the protocol to an unsupported language can verify the wire behaviour. > **Use an SDK.** Do not implement this by hand for production. The official SDKs (Python today, JavaScript in progress) perform the handshake, serialize protobuf, manage nonces, and encrypt/decrypt every frame. The spec below is reference material. ## Scope | Applies to | Does not apply to | | --- | --- | | WebSocket trading ops (`order.place`, `order.cancel`, `order.modify`) | REST endpoints under `/api/v1` (plain HTTPS + bearer) | | Authenticated stream channels (`orders`, `positions`) | Public WebSocket channels (`instruments`, `transparency`) | | | Market-data proxies (unauthenticated) | REST is encrypted by TLS only. The extra layer described here is specific to authenticated WebSocket trading, where the gateway must not see plaintext orders in its logs or memory outside a well-defined decryption boundary. ## Session lifecycle A session is the unit of shared-key material. Every new WebSocket connection establishes a fresh session; the session ends when the socket closes (or a rekey is requested). The four steps, in order: 1. **Authenticate the socket** with `op: "login"` and a bearer token — see [Authentication](https://docs.godarkdex.com/docs/authentication) and [WebSocket Trading](https://docs.godarkdex.com/docs/ws-trading). `session.setup` is rejected until `login` succeeds. 2. **Exchange ephemeral keys.** The client generates a fresh X25519 keypair per session and sends the public half via `op: "session.setup"`. The gateway replies with its own fresh X25519 public key and an opaque `session_id`. 3. **Derive the session key locally.** Both sides run X25519 ECDH on the pair and expand through HKDF-SHA256 into a 256-bit AES key (`K`). The shared secret never traverses the wire. 4. **Encrypt every trading op** under `K` with AES-256-GCM. Responses (`ack`, `order_update`, `position_update`) are returned encrypted under the same `K` and decrypted client-side. ### op: session.setup Client → server, after `op: "login"` has succeeded on the same socket: ```json { "id": "c-2", "op": "session.setup", "args": { "client_ecdh_pubkey": "" } } ``` Server response: ```json { "id": "c-2", "op": "session.setup", "code": 0, "data": { "session_id": "9007199254740993", "server_ecdh_pubkey": "" } } ``` | Field | Type | Notes | | --- | --- | --- | | `client_ecdh_pubkey` | base64(32 bytes) | Raw X25519 public key per RFC 7748. Fresh per session. | | `server_ecdh_pubkey` | base64(32 bytes) | Gateway's ephemeral X25519 public key. Not a long-lived committee key; rotated per session. | | `session_id` | string (u64 decimal) | Opaque gateway-assigned identifier; must be treated as an integer for the nonce construction below. | `server_ecdh_pubkey` is an **ephemeral, session-scoped** public key delivered in-band by the gateway. It is not a static committee identity key. The session key derived from it binds the channel to this specific `(client_pk, server_pk)` pair and provides forward secrecy: once the session ends and both sides discard their private halves, past traffic cannot be decrypted. ### Rekey The server may emit an unsolicited `rekey_required` event (for example before internal `session_id` exhaustion, or on a scheduled rotation). Clients MUST: 1. Stop sending encrypted ops. 2. Run `session.setup` again on the same socket with a fresh client keypair. 3. Reset the send-nonce counter to zero. 4. Resume encrypted ops under the new key. Subscriptions and `login` state are preserved across a rekey; only the symmetric key and nonce counter are rotated. ## Key derivation Given the two 32-byte X25519 public keys (`client_pk`, `server_pk`) and the client's private key: ``` ikm = X25519(client_private, server_pk) // 32-byte shared secret salt = min(client_pk, server_pk) || max(client_pk, server_pk) // 64 bytes info = "gdx-e2e-session-key-v1" // ASCII K = HKDF-SHA256(ikm, salt=salt, info=info, length=32) ``` Rules: - `min` / `max` is a byte-lexicographic comparison of the two raw 32-byte public keys. This makes the salt symmetric — both sides compute the same HKDF input without exchanging extra bytes. - If `ikm == 0x00…00` (32 zero bytes), the peer sent a small-subgroup public key. Clients MUST abort the session with `invalid_public_key`. - `info` is a fixed ASCII constant. The `-v1` suffix is the protocol version — if the KDF ever changes, `info` changes too, so old and new keys never collide. - Output length is fixed at 32 bytes → AES-256-GCM key. There is no separate MAC key; GCM provides authenticity. ## Frame encryption AES-256-GCM, 96-bit nonce, 128-bit authentication tag. Tag is appended to the ciphertext in standard GCM concatenated form: ``` wire_body = AES-GCM-Encrypt(K, nonce, plaintext, aad) // ciphertext || 16-byte tag ``` ### Nonce construction ``` nonce = session_id (8 bytes, big-endian) || counter (4 bytes, big-endian) ``` | Field | Size | Rules | | --- | --- | --- | | `session_id` | u64 big-endian | Same value returned by `session.setup`. Never repeats within a session's lifetime (it's the session itself). | | `counter` | u32 big-endian | Starts at `0` per session, incremented by exactly `1` per encrypted frame you send. Never reused. Receive-side is tracked separately. | Counter overflow (> `2^32 - 1` frames in one session) is a hard error — the client MUST close the session and rekey. The SDK raises `EncryptionError` / `nonce_overflow` before sending an overflowed frame. ### Associated data (AAD) Every frame carries a protobuf-encoded header as AES-GCM AAD — authenticated but not encrypted. This binds the ciphertext to routing metadata the gateway needs to read before it can decrypt, and prevents a compromised intermediary from swapping headers between frames. **Requests — `OrderHeader` AAD (client → server):** | Field | Type | Notes | | --- | --- | --- | | `user_uuid` | `bytes` (16) | RFC 4122 UUID, big-endian. Must match the login-bound account. | | `symbol_id` | `uint32` | Resolved instrument id. | | `request_type` | enum | `place` / `cancel` / `modify`. Must match the outer `op`. | | `nonce` | `uint32` | Same counter used to build the GCM nonce. | | `body_length` | `uint32` | `len(plaintext) + 16` (ciphertext includes the auth tag). | **Responses — `ResponseHeader` AAD (server → client):** | Field | Type | Notes | | --- | --- | --- | | `user_uuid` | `bytes` (16) | Always the authenticated UUID — **never trust the envelope copy**, always re-derive from your session state. | | `message_type` | enum | `ack` / `order_update` / `position_update` / `system_health`. | | `body_length` | `uint32` | `len(ciphertext)` including the 16-byte tag. | | `nonce` | `uint32` | Server-side send counter for this direction. | | `fencing_epoch` | `uint32` | Epoch for replay/fencing guards across reconnect. | AAD bytes must be **byte-identical** to what the server produces for the same logical fields; if your protobuf encoding differs by even one byte, GCM tag verification fails with `InvalidTag`. In practice this means: use the generated protobuf classes from `gdx-core/crates/gdx-wire/proto/`, emit default-valued fields exactly as the canonical encoder does, and preserve field ordering. ### Encrypted request envelope After `session.setup`, trading ops carry their protobuf body encrypted. The logical `args` you would have sent are replaced with a single encrypted blob plus header metadata: ```json { "id": "c-10", "op": "order.place", "args": { "header": { "symbol_id": 1, "request_type": "place", "nonce": 0, "body_length": 158 }, "ciphertext": "" } } ``` - `args.header` is the same struct the SDK serialized as AAD. It's echoed here in JSON (not protobuf) so the gateway can route without decrypting, and the client can sanity-check what the gateway saw. - `args.ciphertext` is the AES-GCM output; plaintext is the protobuf-serialized `EdgeSequencerRequest` (the union of `PlaceOrderInput` / `CancelMessage` / `ModifyOrderInput`). See each endpoint's page for the plaintext field list. - `user_uuid` is intentionally omitted from the envelope. The gateway binds the session to the `login`-authenticated UUID; any `user_uuid` a client might put on the wire is ignored. ### Encrypted response envelope Responses — both the synchronous ack for a trading op and streaming channel pushes — come back the same way: ```json { "id": "c-10", "op": "order.place", "code": 0, "data": { "header": { "message_type": "ack", "body_length": 42, "nonce": 0, "fencing_epoch": 7 }, "ciphertext": "" } } ``` Stream pushes (`orders`, `positions`) follow the same shape but with `channel` + `type` + `seq` at the top level instead of `id` + `op` + `code` — see [WebSocket Trading](https://docs.godarkdex.com/docs/ws-trading) for the un-encrypted envelope skeleton. Plaintext of an ack is a protobuf `NodeResponse`; plaintext of a stream push is a protobuf `SequencerToEdgeMessage`. Parse, then map into the public types documented in [Orders Channel](https://docs.godarkdex.com/docs/order-updates) and [Positions Channel](https://docs.godarkdex.com/docs/ws-user-events). ## Security properties | Property | How it's achieved | | --- | --- | | **Confidentiality** of order contents | AES-256-GCM under `K`. `K` derives from ECDH with ephemeral keys on both sides; the shared secret never traverses the wire. | | **Forward secrecy** | X25519 private keys are ephemeral per session. Discarding them after session end makes recorded ciphertext undecryptable. | | **Integrity & authenticity** | 128-bit GCM tag over ciphertext + AAD. Any mutation of the header, ciphertext, or tag fails verification with `decrypt_failed`. | | **Identity binding** | AAD includes the user UUID; the gateway compares it to the `login`-authenticated UUID before accepting the frame. A stolen session cannot be replayed under a different account. | | **Replay resistance (within a session)** | Receive-side nonce tracking rejects reused or out-of-order counters with `nonce_out_of_order`. | | **Replay resistance (across sessions)** | `session_id` is part of the GCM nonce, so frames encrypted in one session can't decrypt in another even under the same key. Sessions are unique. | | **Reordering across reconnect** | Response `fencing_epoch` increments on each server-side session rotation; a stale client rejects frames whose epoch has moved. | ### What this channel does **not** give you - **Authenticity of the gateway's identity.** `server_ecdh_pubkey` is an ephemeral key delivered in-band. Clients trust it transitively through TLS + bearer-token authentication to the gateway, not through a pinned long-lived public key. If an operator rotates the edge deployment, there is no key-pinning alarm. - **Protection against a malicious gateway.** A compromised gateway sees plaintext orders after decryption. The encryption layer protects orders from passive observers and from logs / traces; it does not make GoDark non-custodial with respect to the operator. Committee-held decryption keys and threshold schemes are a separate design (not this channel). ## Error codes All failures here surface through the standard error path — `code` non-zero on an op response, or a `code`-bearing event if the failure is asynchronous. | Code | When | | --- | --- | | `session_required` | Trading op sent before `session.setup` completed on this socket. | | `session_expired` | Gateway retired the session; client must rerun `session.setup`. | | `invalid_public_key` | Client or server public key was not 32 bytes, was the neutral element, or produced an all-zero shared secret. | | `decrypt_failed` | AES-GCM tag verification failed. Causes: wrong key, AAD mismatch (header bytes or identity), flipped bits, or mismatched `session_id` in the nonce. | | `nonce_out_of_order` | Receive-side nonce tracker saw a counter it won't accept (reuse, regression, or an unacceptable jump). | | `nonce_overflow` | Send counter would exceed `2^32 - 1` within a single session. Rekey. | | `rekey_required` | Gateway asked the client to rerun `session.setup`. Not an error per se; treated as a directive. | See [Error Codes](https://docs.godarkdex.com/docs/error-codes) for the cross-cutting list. ## Reference implementation The Python SDK under `gdx-sdk/python/` is the reference. The interesting files: | File | What to look at | | --- | --- | | `src/godark/_crypto.py` | X25519 keypair generation, HKDF salt construction, `build_gcm_nonce`, `encrypt` / `decrypt`. | | `src/godark/_session.py` | `CryptoSession` lifecycle: `generate_keypair` → `establish` → `encrypt_order` / `decrypt_push` → `reset`. | | `src/godark/_proto.py` | `build_order_header_aad`, `build_response_header_aad` — the AAD byte layout the gateway expects. | | `src/godark/client.py` | `_setup_ecdh_session`, `_send_encrypted_order`, `_handle_encrypted_push` — the full request / response pipeline. | The JavaScript SDK reference implementation is tracked on the `feat/production-readiness` branch and follows the same primitives. --- ================================================================================ Source: https://docs.godarkdex.com/docs/get-instruments/ # Get Instruments List all instruments available for trading. Clients should call this once on startup and refresh on a timer or when an `If-None-Match` request indicates a new `version`. ``` GET /instruments GET /instruments/{symbol} ``` Auth: Public. No token required. ## Available Symbols All instruments are USDC-quoted linear perpetuals. Symbols follow the `BASE-USDC-PERP` format. | Symbol | Base asset | | --- | --- | | `AAVE-USDC-PERP` | AAVE | | `ADA-USDC-PERP` | ADA | | `APT-USDC-PERP` | APT | | `ARB-USDC-PERP` | ARB | | `AVAX-USDC-PERP` | AVAX | | `BNB-USDC-PERP` | BNB | | `BTC-USDC-PERP` | BTC | | `DOGE-USDC-PERP` | DOGE | | `DOT-USDC-PERP` | DOT | | `ETH-USDC-PERP` | ETH | | `HYPE-USDC-PERP` | HYPE | | `LINK-USDC-PERP` | LINK | | `NEAR-USDC-PERP` | NEAR | | `PEPE-USDC-PERP` | PEPE | | `POL-USDC-PERP` | POL | | `SOL-USDC-PERP` | SOL | | `SUI-USDC-PERP` | SUI | | `TRX-USDC-PERP` | TRX | | `UNI-USDC-PERP` | UNI | | `XRP-USDC-PERP` | XRP | This table is a snapshot; `GET /instruments` below is always the source for the live set (status, tick sizes, fees, etc.). ## List All Instruments ```bash curl https://api.godarkdex.com/api/v1/instruments ``` ### Response ```json { "code": 0, "data": { "version": 842, "updated_at": "2026-04-20T00:00:00Z", "instruments": [ { "symbol": "BTC-USDC-PERP", "base_asset": "BTC", "quote_asset": "USDC", "type": "perp", "status": "trading", "tick_size": 0.1, "step_size": 0.001, "min_qty": 0.001, "max_qty": 1000, "min_notional": 25, "contract_size": 1, "margin_asset": "USDC", "max_leverage": 20, "maker_fee_bps": 2, "taker_fee_bps": 5, "initial_margin_ratio": 0.05, "maintenance_margin_ratio": 0.025, "listed_at": "2026-01-01T00:00:00Z", "expires_at": null } ] }, "timestamp": "2026-04-20T10:30:00.123Z", "request_id": "req_01HXYZ..." } ``` ## Single Instrument ```bash curl https://api.godarkdex.com/api/v1/instruments/BTC-USDC-PERP ``` Returns the same instrument object under `data` (not wrapped in an `instruments` array). ## Field Reference | Field | Type | Description | | --- | --- | --- | | `symbol` | string | Canonical id used on all other endpoints | | `base_asset` | string | Base asset (e.g. `BTC`) | | `quote_asset` | string | Quote asset (always `USDC`) | | `type` | string | `perp` (currently the only type) | | `status` | string | `trading`, `halted`, `pre-open`, or `delisted` | | `tick_size` | number | Minimum price increment (quote asset) | | `step_size` | number | Minimum quantity increment (base asset) | | `min_qty` | number | Minimum order quantity | | `max_qty` | number | Maximum order quantity | | `min_notional` | number | Minimum order notional (USDC) | | `contract_size` | number | Contract multiplier (1 for linear perps) | | `margin_asset` | string | Collateral asset (always `USDC`) | | `max_leverage` | number | Maximum leverage permitted on this instrument | | `maker_fee_bps` | number | **Default** maker fee (negative = rebate). See caveat below. | | `taker_fee_bps` | number | **Default** taker fee. See caveat below. | | `initial_margin_ratio` | number | Initial margin requirement (see [Margin & Liquidation](https://docs.godarkdex.com/docs/margin-and-liquidation)) | | `maintenance_margin_ratio` | number | Maintenance margin requirement (see [Margin & Liquidation](https://docs.godarkdex.com/docs/margin-and-liquidation)) | | `listed_at` | string | Listing timestamp (RFC 3339) | | `expires_at` | string \| null | Expiry timestamp (always `null` for perps) | ## Fee Authority `maker_fee_bps` and `taker_fee_bps` on this endpoint are **instrument-level defaults**, not your effective fees. Your actual fees are driven by your VIP tier and always live at [`GET /account/vip`](https://docs.godarkdex.com/docs/vip-tiers). When they differ, `/account/vip` wins. ## Cache Semantics The list response carries: - `version` — monotonically increasing integer, bumped whenever any field on any instrument changes. - `updated_at` — RFC 3339 timestamp of the last change. Responses include an `ETag` header matching `version`. Clients should cache the list and pass `If-None-Match: ""` on subsequent calls; unchanged lists return `304 Not Modified` with an empty body. ## Instrument Status Changes Intraday status changes (halts, new listings) are pushed on the public `instruments` WebSocket channel — subscribe to receive `snapshot` on connect and `update` on each change. Clients that don't need reactivity can just refresh on a timer instead. --- ================================================================================ Source: https://docs.godarkdex.com/docs/account-info/ # Account Info A single call that returns your account balance, current VIP tier, and basic account-level configuration. Call this once at login to populate client state; fetch on demand rather than polling. Available as a REST endpoint and as a WebSocket op with an identical response body. ## GET /account ``` GET /account ``` Auth: `Authorization: Bearer `. ```bash curl https://api.godarkdex.com/api/v1/account \ -H "Authorization: Bearer $TOKEN" ``` ### Response ```json { "code": 0, "data": { "account_id": "acct_01HXYZ", "wallet": "CusT0dyVaU1t...", "status": "active", "balance": { "asset": "USDC", "total": "125430.250000", "available": "98210.500000", "locked_in_orders": "12000.000000", "locked_as_margin": "15219.750000" }, "vip": { "tier": 2, "name": "Advanced", "maker_fee_bps": 0, "taker_fee_bps": 3, "rolling_30d_volume_usd": "12450000.00" }, "config": { "default_leverage": 5, "margin_mode": "isolated", "cancel_on_disconnect": false, "self_trade_prevention": "cancel_taker", "preferred_quote_asset": "USDC" } }, "timestamp": "2026-04-20T10:30:00.123Z", "request_id": "req_01HXYZ..." } ``` ### Field Reference **Top-level** | Field | Type | Description | | --- | --- | --- | | `account_id` | string | Stable account identifier. Same value returned on `op: login`. | | `wallet` | string | Solana wallet address bound to the account. | | `status` | string | `active`, `restricted`, or `suspended`. | **`balance`** | Field | Type | Description | | --- | --- | --- | | `asset` | string | Collateral asset. Always `USDC`. | | `total` | string | `available` + `locked_in_orders` + `locked_as_margin`. | | `available` | string | Free collateral — usable for new orders or withdrawal. | | `locked_in_orders` | string | Collateral reserved against resting orders. | | `locked_as_margin` | string | Collateral posted as margin against open positions. | **`vip`** Snapshot of fee-bearing VIP state. For the authoritative per-tier schedule and next-tier progress, use [`GET /account/vip`](https://docs.godarkdex.com/docs/vip-tiers). | Field | Type | Description | | --- | --- | --- | | `tier` / `name` | integer / string | Current tier level and label. | | `maker_fee_bps` / `taker_fee_bps` | number | Your effective fees (negative maker = rebate). | | `rolling_30d_volume_usd` | string | Qualifying notional volume over the last 30 days. | **`config`** | Field | Type | Description | | --- | --- | --- | | `default_leverage` | number | Leverage applied when an order omits an explicit value. | | `margin_mode` | string | `isolated` (currently the only supported mode). | | `cancel_on_disconnect` | boolean | Account-level default for WebSocket cancel-on-disconnect. Per-session opt-in on `op: login` overrides this. | | `self_trade_prevention` | string | One of `cancel_taker`, `cancel_maker`, `cancel_both`. | | `preferred_quote_asset` | string | Quote asset shown by default in the app. Does not affect matching or settlement. | ## op: account.info Same response body, delivered over the authenticated WebSocket. ```json { "id": "c-20", "op": "account.info" } ``` Response: ```json { "id": "c-20", "op": "account.info", "code": 0, "data": { "account_id": "acct_01HXYZ", "wallet": "CusT0dyVaU1t...", "status": "active", "balance": { "asset": "USDC", "total": "125430.250000", "available": "98210.500000", "locked_in_orders": "12000.000000", "locked_as_margin": "15219.750000" }, "vip": { "tier": 2, "name": "Advanced", "maker_fee_bps": 0, "taker_fee_bps": 3, "rolling_30d_volume_usd": "12450000.00" }, "config": { "default_leverage": 5, "margin_mode": "isolated", "cancel_on_disconnect": false, "self_trade_prevention": "cancel_taker", "preferred_quote_asset": "USDC" } } } ``` Requires a prior successful `op: login`. See [WebSocket Trading](https://docs.godarkdex.com/docs/ws-trading). ## Errors | Status | Code | Meaning | | --- | --- | --- | | `401` | `not_authenticated` | Missing or expired bearer token. | | `403` | `account_restricted` | Account status is `restricted` or `suspended`. | Full list: [Error Codes](https://docs.godarkdex.com/docs/error-codes). ================================================================================ Source: https://docs.godarkdex.com/docs/positions/ # Positions Snapshot of the authenticated account's open positions. ``` GET /positions ``` Auth: `Authorization: Bearer `. The account is derived from the token — there is no path parameter for user id. ## Query Parameters | Parameter | Required | Description | | --- | --- | --- | | `status` | No | Filter by position status. Accepts `OPEN` (default), `CLOSING`, `CLOSED`. | | `symbol` | No | Filter to a single instrument. | ## Example ```bash curl "https://api.godarkdex.com/api/v1/positions?status=OPEN" \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "code": 0, "data": { "positions": [ { "position_id": "pos_01HXYZ", "symbol": "BTC-USDC-PERP", "side": "long", "size": 0.5, "entry_price": 95000.0, "mark_price": 95500.0, "margin": 4750.0, "leverage": 5, "unrealized_pnl": 250.0, "realized_pnl": 0, "funding_accrued": -12.5, "liquidation_price": 85500.0, "status": "OPEN", "created_at": "2026-04-20T10:30:00.123Z", "updated_at": "2026-04-20T11:00:00.456Z" } ] }, "timestamp": "2026-04-20T11:05:00.789Z", "request_id": "req_01HXYZ..." } ``` ## Field Reference | Field | Type | Description | | --- | --- | --- | | `position_id` | string | Position id | | `symbol` | string | Instrument id | | `side` | string | `long` or `short` | | `size` | number | Position size in base asset (always positive; direction is given by `side`) | | `entry_price` | number | Volume-weighted average entry price | | `mark_price` | number | Reference price used for PnL and liquidation math | | `margin` | number | Collateral allocated to this position (USDC) | | `leverage` | number | Effective leverage | | `unrealized_pnl` | number | Current unrealized PnL (USDC) | | `realized_pnl` | number | Cumulative realized PnL since position opened (USDC) | | `funding_accrued` | number | Net funding paid/received (USDC; negative = paid out) | | `liquidation_price` | number | Price at which this position would be liquidated (see [Margin & Liquidation](https://docs.godarkdex.com/docs/margin-and-liquidation#liquidation-price)) | | `status` | string | `OPEN`, `CLOSING`, or `CLOSED` | | `created_at` | string | Position open timestamp (RFC 3339) | | `updated_at` | string | Last update timestamp (RFC 3339) | ## Streaming Alternative `GET /positions` is a single snapshot. For live updates — fills, mark price moves, liquidation-price changes — subscribe to the [Positions Channel](https://docs.godarkdex.com/docs/ws-user-events) over WebSocket. The channel sends a snapshot on subscribe and then incremental updates. For margin health tiers, partial liquidation, and how `liquidation_price` is derived, see [Margin & Liquidation](https://docs.godarkdex.com/docs/margin-and-liquidation). --- ================================================================================ Source: https://docs.godarkdex.com/docs/vip-tiers/ # VIP Tiers VIP tiers govern your fee schedule and rate limits. Two endpoints: - `GET /vip/tiers` — public schedule of all tiers. - `GET /account/vip` — your current tier, rolling volume, and progress toward the next tier. ## GET /vip/tiers Public, unauthenticated. Use this to render a fee table or explain tiering to users. ```bash curl https://api.godarkdex.com/api/v1/vip/tiers ``` ### Response ```json { "code": 0, "data": { "tiers": [ { "tier": 0, "name": "Core", "min_30d_volume_usd": 0, "maker_fee_bps": 2, "taker_fee_bps": 5, "min_order_notional_usd": 25, "rate_limits": { "rest_per_min": 1200, "ws_msgs_per_sec": 30 } }, { "tier": 1, "name": "Select", "min_30d_volume_usd": 5000000, "maker_fee_bps": 1, "taker_fee_bps": 4, "min_order_notional_usd": 50, "rate_limits": { "rest_per_min": 2400, "ws_msgs_per_sec": 60 } }, { "tier": 2, "name": "Advanced", "min_30d_volume_usd": 10000000, "maker_fee_bps": 0, "taker_fee_bps": 3, "min_order_notional_usd": 75, "rate_limits": { "rest_per_min": 4800, "ws_msgs_per_sec": 120 } }, { "tier": 3, "name": "Prime", "min_30d_volume_usd": 25000000, "maker_fee_bps": -0.5, "taker_fee_bps": 2.5, "min_order_notional_usd": 90, "rate_limits": { "rest_per_min": 9600, "ws_msgs_per_sec": 240 } }, { "tier": 4, "name": "Apex", "min_30d_volume_usd": 50000000, "maker_fee_bps": -1, "taker_fee_bps": 2, "min_order_notional_usd": 100, "rate_limits": { "rest_per_min": 19200, "ws_msgs_per_sec": 480 } } ] }, "timestamp": "2026-04-20T10:30:00.123Z" } ``` Negative `maker_fee_bps` values are rebates. ## GET /account/vip Authoritative source for **your** fee schedule. Use this at login and refresh daily. ``` GET /account/vip ``` Auth: `Authorization: Bearer `. ```bash curl https://api.godarkdex.com/api/v1/account/vip \ -H "Authorization: Bearer $TOKEN" ``` ### Response ```json { "code": 0, "data": { "tier": 2, "name": "Advanced", "maker_fee_bps": 0, "taker_fee_bps": 3, "min_order_notional_usd": 75, "rate_limits": { "rest_per_min": 4800, "ws_msgs_per_sec": 120 }, "rolling_30d_volume_usd": "12450000.00", "next_tier": { "tier": 3, "name": "Prime", "volume_to_reach_usd": "12550000.00" }, "effective_from": "2026-04-01T00:00:00Z", "recomputed_at": "2026-04-20T00:00:00Z" }, "timestamp": "2026-04-20T10:30:00.123Z", "request_id": "req_01HXYZ..." } ``` ### Field Reference | Field | Description | | --- | --- | | `tier` / `name` | Current tier level and label | | `maker_fee_bps` / `taker_fee_bps` | **Your** effective fees (authoritative — see below) | | `min_order_notional_usd` | Minimum order notional at your tier | | `rate_limits` | Your current rate-limit budgets | | `rolling_30d_volume_usd` | Qualifying notional volume over the last 30 days | | `next_tier.volume_to_reach_usd` | Additional 30d volume required to advance | | `effective_from` | When your current tier took effect | | `recomputed_at` | When tier was last evaluated (daily at 00:00 UTC) | ## Recomputation Cadence Tiers are re-evaluated once per day at 00:00 UTC based on rolling 30d volume. Intraday volume increases are reflected in `rolling_30d_volume_usd` but do not change `tier` until the next evaluation. ## Fee Authority When `GET /instruments` shows different `maker_fee_bps` / `taker_fee_bps` than `GET /account/vip`, `/account/vip` is authoritative. Instrument fees are **defaults** applied to tier 0. Execution reports and settlement charges always use your tier-adjusted rates. See [Fee Structure](https://docs.godarkdex.com/docs/fee-structure) for how fees are collected and settled. --- ================================================================================ Source: https://docs.godarkdex.com/docs/transparency/ # Transparency GoDark publishes all verifiable venue data through **one public endpoint**. No token, no bearer header, no account — a single `GET` returns every transparency surface for the current epoch, so anyone can consume it the same way. | Surface | Endpoint | Auth | What it proves | | --- | --- | --- | --- | | Venue transparency | `GET /transparency` | Public | Solvency, engine identity, and aggregate activity for the current epoch | Epochs are sequential integers. A new epoch is published every 60 minutes on the hour (UTC). ## GET /transparency Returns the latest epoch snapshot: proof-of-reserves root, engine attestation, and aggregate market/operations/node stats — in one response. ```bash curl https://api.godarkdex.com/api/v1/transparency ``` ### Query Parameters | Parameter | Accepted values | Default | Notes | | --- | --- | --- | --- | | `epoch` | integer | current | Return a historical snapshot. Epochs older than 365 days may be pruned from hot storage; the gateway returns `404 epoch_not_available`. | | `window` | `1h`, `24h`, `7d`, `30d` | `24h` | Window applied to aggregate stats. Reserves and attestation are always the epoch snapshot. | ### Response ```json { "code": 0, "data": { "epoch": 842, "published_at": "2026-04-20T10:00:00Z", "previous_epoch_root": "0x2e1c...a88f", "next_epoch_at": "2026-04-20T11:00:00Z", "reserves": { "merkle_root": "0x7a9f...c12b", "hash_algo": "sha256", "total_liabilities_usd": "124300000.00", "accounts": [ { "asset": "USDC", "chain": "solana", "address": "CusT0dyVaU1t...", "balance": "128450000.000000", "proof_tx": "5XyZ..." } ] }, "attestation": { "engine": { "code_hash": "sha256:4f19...de02", "tee": { "type": "SGX", "quote": "base64:AAAAB3Nz...==", "verified_at": "2026-04-20T09:59:58Z" } }, "committee": { "threshold": "3-of-5", "rotation_epoch": 840, "members": [ { "id": "mpc-a", "operator": "Region US-East", "pubkey": "0xab12..." }, { "id": "mpc-b", "operator": "Region EU-West", "pubkey": "0xcd34..." }, { "id": "mpc-c", "operator": "Region APAC", "pubkey": "0xef56..." }, { "id": "mpc-d", "operator": "Region US-West", "pubkey": "0x7890..." }, { "id": "mpc-e", "operator": "Region EU-North", "pubkey": "0x12ab..." } ] }, "signatures": [ { "signer": "mpc-a", "sig": "0x..." }, { "signer": "mpc-b", "sig": "0x..." }, { "signer": "mpc-c", "sig": "0x..." } ] }, "stats": { "window": "24h", "as_of": "2026-04-20T10:00:00Z", "market": { "matched_volume_usd": "84250000.00", "liquidity_submitted_usd": "1420800000.00", "buy_sell_ratio": 1.03, "avg_time_to_fill_ms": 412, "unique_wallets": 1847, "avg_order_size_usd": "5823.10", "matched_trade_count": 48210, "order_count": 244110 }, "operations": { "fees_collected_usd": "42180.55", "avg_settlement_finality_ms": 1820, "ephemeral_wallet_assets_usd": "3121000.00", "failed_settlements": 0, "system_downtime_seconds": 0, "avg_api_response_ms": 38 }, "nodes": { "live_sequencer_nodes": 3, "live_verifier_nodes": 5, "total_nodes": 8, "node_network_24h_uptime_pct": 99.998 } } }, "timestamp": "2026-04-20T10:30:00.123Z" } ``` ### Reserves Fields | Field | Type | Description | | --- | --- | --- | | `merkle_root` | string | Root of the published reserves tree for this epoch. | | `hash_algo` | string | Hash used to build the tree. | | `total_liabilities_usd` | string | Sum of liabilities the reserves back. | | `accounts[].asset` | string | Asset symbol held in the reserve. | | `accounts[].chain` | string | Chain the reserve lives on. | | `accounts[].address` | string | On-chain address to audit directly. | | `accounts[].balance` | string | Balance recorded at snapshot time. | | `accounts[].proof_tx` | string | Transaction hash that anchors the snapshot on-chain. | ### Attestation Fields | Field | Type | Description | | --- | --- | --- | | `engine.code_hash` | string | Hash of the engine binary running this epoch. | | `engine.tee.type` | string | TEE technology backing the engine. | | `engine.tee.quote` | string | Base64 TEE quote that can be verified against the vendor's attestation service. | | `committee.threshold` | string | Signing threshold of the matching committee (e.g. `3-of-5`). | | `committee.members[]` | array | Committee members and their public keys. | | `committee.rotation_epoch` | integer | Last epoch at which the committee rotated. | | `signatures[]` | array | Threshold signatures over the epoch snapshot. | ### Stats Fields **Market** | Field | Type | Description | | --- | --- | --- | | `matched_volume_usd` | string | Notional value of matched trades in the window. | | `liquidity_submitted_usd` | string | Total notional of orders submitted in the window (includes cancels and unfilled rest). | | `buy_sell_ratio` | number | Buy-side notional divided by sell-side notional. `1.0` = balanced flow. | | `avg_time_to_fill_ms` | integer | Average latency from order acceptance to first fill, across matched orders. | | `unique_wallets` | integer | Distinct wallets that submitted at least one order in the window. | | `avg_order_size_usd` | string | Average notional per submitted order (not per fill). | | `matched_trade_count` | integer | Number of discrete fills in the window. | | `order_count` | integer | Number of orders submitted in the window. | **Operations** | Field | Type | Description | | --- | --- | --- | | `fees_collected_usd` | string | Total venue fees collected in the window. | | `avg_settlement_finality_ms` | integer | Average time from match to Solana-finalized settlement. | | `ephemeral_wallet_assets_usd` | string | Point-in-time balance across transient ephemeral wallets used for settlement flow. Gauge, not window-scoped. | | `failed_settlements` | integer | Settlement batches that failed on-chain and required replay in the window. | | `system_downtime_seconds` | integer | Total seconds the venue was unavailable to accept trading during the window. | | `avg_api_response_ms` | integer | Average REST response latency across trading endpoints in the window. | **Nodes** | Field | Type | Description | | --- | --- | --- | | `live_sequencer_nodes` | integer | Attested sequencer nodes currently participating. Gauge. | | `live_verifier_nodes` | integer | Verifier nodes currently online. Gauge. | | `total_nodes` | integer | Total nodes provisioned across the committee. Gauge. | | `node_network_24h_uptime_pct` | number | Aggregate uptime across the node network over the last 24 hours. | No per-trade or per-user data is returned — only venue-level aggregates and on-chain anchors. This endpoint is safe to embed in public dashboards and to scrape unauthenticated. ## WebSocket Notifications Subscribe to the public `transparency` channel on `wss://api.godarkdex.com/ws/v1` to be notified whenever a new epoch is published — no polling required: ```json { "id": "c-1", "op": "subscribe", "args": { "channel": "transparency" } } ``` Events carry only the epoch number and root; fetch the full snapshot via `GET /transparency` when you need it. ================================================================================ Source: https://docs.godarkdex.com/docs/settlement-status/ # Settlement Status Query the status of settlement batches. ## Get Batch Status ``` GET /settlement/status/{batchId} ``` Auth: `Authorization: Bearer `. ### Example ```bash curl https://api.godarkdex.com/api/v1/settlement/status/batch_01HXYZ123 \ -H "Authorization: Bearer $TOKEN" ``` ### Response ```json { "code": 0, "data": { "batch_id": "batch_01HXYZ123", "status": "SETTLED", "tx_signature": "5xKXtg2CW87d9Z...", "trade_count": 42, "created_at": "2026-04-20T10:30:00.123Z", "settled_at": "2026-04-20T10:30:00.520Z" }, "timestamp": "2026-04-20T10:30:01.000Z", "request_id": "req_01HXYZ..." } ``` ### Status Values | Status | Description | | --- | --- | | `PENDING` | Batch is being assembled | | `PROCESSING` | Settlement transaction submitted | | `SETTLED` | On-chain settlement confirmed | | `FAILED` | Settlement failed (will retry) | ## Settlement Timing | Stage | Typical Duration | | --- | --- | | Batch assembly | 1–2 seconds | | On-chain confirmation | Typically begins around Solana slot time (~400ms); finalized settlement follows Solana finality | | Total end-to-end | < 5 seconds typical | ## Verifying Settlement Each settlement transaction can be verified on-chain using the returned `tx_signature`: 1. Use a Solana block explorer (e.g. Solscan, Solana Explorer). 2. Look up the `tx_signature` to view transaction detail. 3. Verify shielded-pool state updates, aggregate collateral movement, and fee transfers. For aggregate, account-agnostic settlement and reserve data, see [Transparency](https://docs.godarkdex.com/docs/transparency). --- ================================================================================ Source: https://docs.godarkdex.com/docs/place-order/ # Place Order Submit a new order. ``` POST /orders ``` Auth: `Authorization: Bearer ` (see [Authentication](https://docs.godarkdex.com/docs/authentication)). ## Request Body | Field | Type | Required | Description | | --- | --- | --- | --- | | `symbol` | string | Yes | Instrument id (e.g. `"BTC-USDC-PERP"`) | | `side` | string | Yes | `"buy"` or `"sell"` | | `type` | string | Yes | `"market"`, `"limit"`, or `"peg"` | | `quantity` | number | Yes | Order size in base asset (must be > 0) | | `price` | number | Conditional | Required for `limit`. Optional for `market` (acts as price cap). Omitted for `peg`. | | `peg_reference` | string | Conditional | Required for `peg`: `"mid"`, `"bid"`, or `"ask"`. | | `time_in_force` | string | Yes | `"GTC"`, `"GTT"`, `"IOC"`, or `"FOK"` | | `expiry_time` | integer | For `GTT` | Nanosecond epoch timestamp at which a `GTT` order expires | | `aon` | boolean | No | All-or-None. Default `false`. See [Execution Attributes](https://docs.godarkdex.com/docs/execution-attributes). | | `min_fill_size` | number | No | Minimum per-execution fill size | | `client_order_id` | string | No | Client-supplied idempotency key (≤64 chars). Duplicates return the existing order. | See [Order Compatibility](https://docs.godarkdex.com/docs/order-compatibility) for which `type` × `time_in_force` × `aon` combinations are supported. ## Example — Limit Order (GTC) ```bash curl -X POST https://api.godarkdex.com/api/v1/orders \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $TOKEN" \ -d '{ "symbol": "BTC-USDC-PERP", "side": "buy", "type": "limit", "quantity": 0.1, "price": 95000, "time_in_force": "GTC", "client_order_id": "my-order-001" }' ``` ## Example — Market Order (IOC) ```bash curl -X POST https://api.godarkdex.com/api/v1/orders \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $TOKEN" \ -d '{ "symbol": "BTC-USDC-PERP", "side": "buy", "type": "market", "quantity": 0.05, "time_in_force": "IOC" }' ``` ## Example — Peg to Mid (GTC) ```bash curl -X POST https://api.godarkdex.com/api/v1/orders \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $TOKEN" \ -d '{ "symbol": "BTC-USDC-PERP", "side": "buy", "type": "peg", "peg_reference": "mid", "quantity": 0.1, "time_in_force": "GTC" }' ``` ## Success Response ```json { "code": 0, "data": { "order_id": "ord_01HXYZ12345", "client_order_id": "my-order-001", "status": "NEW" }, "timestamp": "2026-04-20T10:30:00.123Z", "request_id": "req_01HXYZ..." } ``` `order_id` is returned as a string to preserve precision. Use it on `DELETE /orders/{orderId}`, `PATCH /orders/{orderId}`, and `GET /orders/{orderId}`. A `200` response means the order passed pre-trade risk checks and entered the book — not that it has filled. Track fills via `GET /orders/{orderId}` or the [Orders Channel](https://docs.godarkdex.com/docs/order-updates). ## Idempotency Supplying `client_order_id` makes `POST /orders` safely retryable: - First request with a given `client_order_id`: creates a new order. - Subsequent requests with the same `client_order_id` (within 24h): return the original order's current state. No duplicate is created. - After 24h, the key is released and reusable. `client_order_id` also works as an identifier on `DELETE /orders?client_order_id=...` and `GET /orders?client_order_id=...`. ## Order Status Lifecycle | Status | Description | | --- | --- | | `NEW` | Order placed and acknowledged | | `PARTIALLY_FILLED` | Partial fill received; remainder working | | `FILLED` | Fully filled | | `CANCELLED` | Cancelled (by user, by TIF expiry, or by system) | | `REJECTED` | Rejected at risk check or by matching engine | Valid transitions: `NEW → PARTIALLY_FILLED → FILLED | CANCELLED`, or `NEW → FILLED | CANCELLED | REJECTED` directly. ## Pre-Trade Risk Validation Every order is risk-checked before it enters the book. A `200` success response means all checks passed. For the full margin model, health tiers, and liquidation ladder, see [Margin & Liquidation](https://docs.godarkdex.com/docs/margin-and-liquidation). | Check | Error Code | | --- | --- | | Margin sufficiency | `1410` | | Position limits | `1411` | | Account in liquidation | `1412` | | Leverage exceeds instrument max | `1413` | ### Risk Rejection Response ```json { "code": 1410, "message": "Margin insufficient: available 1200.00 USDC, required 5000.00 USDC", "timestamp": "2026-04-20T10:30:00.123Z", "request_id": "req_01HXYZ..." } ``` For WebSocket placements (`op: order.place`), the rejection is returned as a `rejected` event on the orders channel with the matching `reject_reason` (see [Rejection Reasons](https://docs.godarkdex.com/docs/order-updates#rejection-reasons)). --- ================================================================================ Source: https://docs.godarkdex.com/docs/cancel-order/ # Cancel Order Cancel a resting order. ``` DELETE /orders/{orderId} ``` Auth: `Authorization: Bearer `. ## Path Parameters | Parameter | Description | | --- | --- | | `orderId` | Order id returned by `POST /orders` | ## Query Parameters (alternative) If you don't have the venue `orderId` handy, you can cancel by your own idempotency key: ``` DELETE /orders?client_order_id={client_order_id} ``` Either `{orderId}` in the path or `client_order_id` in the query is required — exactly one. ## Example — Cancel by Order Id ```bash curl -X DELETE https://api.godarkdex.com/api/v1/orders/ord_01HXYZ12345 \ -H "Authorization: Bearer $TOKEN" ``` ## Example — Cancel by Client Order Id ```bash curl -X DELETE "https://api.godarkdex.com/api/v1/orders?client_order_id=my-order-001" \ -H "Authorization: Bearer $TOKEN" ``` ## Success Response ```json { "code": 0, "data": { "order_id": "ord_01HXYZ12345", "client_order_id": "my-order-001", "status": "CANCELLED", "filled_quantity": 0.03, "remaining_quantity": 0.07, "cancel_reason": "USER_REQUESTED" }, "timestamp": "2026-04-20T10:30:00.123Z", "request_id": "req_01HXYZ..." } ``` The final order state is returned in full so you don't need a follow-up `GET /orders/{orderId}`. ## Errors | Code | Meaning | | --- | --- | | `1400` | Order not found or already in a terminal state (`FILLED`, `CANCELLED`, `REJECTED`) | | `1401` | Order belongs to a different account | See [Error Codes](https://docs.godarkdex.com/docs/error-codes) for the full list. --- ================================================================================ Source: https://docs.godarkdex.com/docs/modify-order/ # Modify Order Amend a resting order's price and/or quantity in place. ``` PATCH /orders/{orderId} ``` Auth: `Authorization: Bearer `. ## Request Body At least one of `price` or `quantity` must be supplied. | Field | Type | Required | Description | | --- | --- | --- | --- | | `price` | number | Conditional | New price | | `quantity` | number | Conditional | New total quantity (not a delta) | Only `limit` orders can be modified. `peg` order prices are derived from `peg_reference` and cannot be set directly — modify `quantity` instead. `market` orders and orders in a terminal state (`FILLED`, `CANCELLED`, `REJECTED`) cannot be modified. ## Example ```bash curl -X PATCH https://api.godarkdex.com/api/v1/orders/ord_01HXYZ12345 \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $TOKEN" \ -d '{ "price": 96000, "quantity": 0.15 }' ``` ## Success Response ```json { "code": 0, "data": { "order_id": "ord_01HXYZ12345", "price": 96000, "quantity": 0.15, "filled_quantity": 0.03, "remaining_quantity": 0.12, "status": "PARTIALLY_FILLED" }, "timestamp": "2026-04-20T10:30:00.123Z", "request_id": "req_01HXYZ..." } ``` ## Queue Priority Modify is implemented as an atomic amend, not cancel-replace. Priority rules: | Change | Queue priority | | --- | --- | | Quantity decrease only | **Preserved** | | Quantity increase (any) | Lost (treated as a new entry at the new size) | | Price change (any) | Lost (re-enters the book at the new price level) | Clients that care about priority should reduce-only rather than reprice where possible. ## Errors | Code | Meaning | | --- | --- | | `1400` | Order not found or in a terminal state | | `1401` | Order belongs to a different account | | `1402` | `type` does not support modification (e.g. `market`) | | `1403` | Neither `price` nor `quantity` supplied | | `1410`–`1413` | Risk check failed against the new order parameters | --- ================================================================================ Source: https://docs.godarkdex.com/docs/get-order/ # Get Order Fetch a single order by id. ``` GET /orders/{orderId} ``` Auth: `Authorization: Bearer `. ## Path Parameters | Parameter | Description | | --- | --- | | `orderId` | Order id returned by `POST /orders` | ## Query Parameters (alternative) Look up by your own idempotency key instead of the venue id: ``` GET /orders?client_order_id={client_order_id} ``` Exactly one of `{orderId}` or `client_order_id` must be supplied. ## Example ```bash curl https://api.godarkdex.com/api/v1/orders/ord_01HXYZ12345 \ -H "Authorization: Bearer $TOKEN" ``` ## Response ```json { "code": 0, "data": { "order_id": "ord_01HXYZ12345", "client_order_id": "my-order-001", "symbol": "BTC-USDC-PERP", "side": "buy", "type": "limit", "peg_reference": null, "quantity": 0.1, "price": 95000, "time_in_force": "GTC", "expiry_time": null, "aon": false, "min_fill_size": null, "status": "PARTIALLY_FILLED", "filled_quantity": 0.03, "remaining_quantity": 0.07, "average_fill_price": 94998.5, "created_at": "2026-04-20T10:30:00.123Z", "updated_at": "2026-04-20T10:31:15.456Z" }, "timestamp": "2026-04-20T10:32:00.789Z", "request_id": "req_01HXYZ..." } ``` ## Field Reference | Field | Type | Description | | --- | --- | --- | | `order_id` | string | Venue-assigned id | | `client_order_id` | string \| null | Idempotency key supplied on placement, if any | | `symbol` | string | Instrument id | | `side` | string | `buy` or `sell` | | `type` | string | `market`, `limit`, or `peg` | | `peg_reference` | string \| null | `mid`, `bid`, or `ask` when `type=peg`, else `null` | | `quantity` | number | Original order quantity | | `price` | number \| null | Limit price, or `null` for `peg` / unpriced `market` | | `time_in_force` | string | `GTC`, `GTT`, `IOC`, or `FOK` | | `expiry_time` | integer \| null | Nanosecond epoch; set for `GTT` | | `aon` | boolean | All-or-None flag | | `min_fill_size` | number \| null | Minimum per-execution fill size, if set | | `status` | string | `NEW`, `PARTIALLY_FILLED`, `FILLED`, `CANCELLED`, `REJECTED` | | `filled_quantity` | number | Total filled so far | | `remaining_quantity` | number | Unfilled remainder | | `average_fill_price` | number \| null | Volume-weighted average fill price | | `created_at` | string | Creation timestamp (RFC 3339) | | `updated_at` | string | Last update timestamp (RFC 3339) | ## Streaming Alternative For live updates on all your orders — including fills, cancels, and rejects — subscribe to the [Orders Channel](https://docs.godarkdex.com/docs/order-updates) over WebSocket rather than polling `GET /orders/{orderId}`. ## Errors | Code | Meaning | | --- | --- | | `1400` | Order not found | | `1401` | Order belongs to a different account | | `1403` | Neither `orderId` nor `client_order_id` supplied | --- ================================================================================ Source: https://docs.godarkdex.com/docs/mass-quote/ # Mass Quote Submit a batch of cancel-replace pairs as a single atomic operation. Designed for market makers who update multiple price levels simultaneously. Available to Prime and Apex tiers only. Mass quotes use the MPC engine's `batch_compare` pipelining, which fuses N comparisons into shared communication rounds with a constant round count. A batch of up to 20 cancel-replace pairs costs roughly the same MPC wall-clock time as 1–2 sequential operations. ## Endpoint ``` POST /orders/mass-quote ``` Auth: `Authorization: Bearer `. Tier must be Prime or Apex — see [VIP Tiers](https://docs.godarkdex.com/docs/vip-tiers). ## Request Body | Field | Type | Required | Description | | --- | --- | --- | --- | | `legs` | array | Yes | Cancel-replace legs (max 20) | Each leg: | Field | Type | Required | Description | | --- | --- | --- | --- | | `cancel_order_id` | string | Yes | Venue order id to cancel | | `symbol` | string | Yes | Instrument id | | `side` | string | Yes | `buy` or `sell` | | `type` | string | No | Must be `limit` (default). Other types are rejected. | | `price` | number | Yes | New order price | | `quantity` | number | Yes | New order quantity | | `time_in_force` | string | No | `GTC` (default) or `GTT`. `IOC` / `FOK` not permitted. | | `expiry_time` | integer | For `GTT` | Nanosecond epoch | | `client_order_id` | string | No | Idempotency key for the replacement leg | ## Example ```bash curl -X POST https://api.godarkdex.com/api/v1/orders/mass-quote \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $TOKEN" \ -d '{ "legs": [ { "cancel_order_id": "ord_01HXYZ001", "symbol": "BTC-USDC-PERP", "side": "buy", "price": 94800, "quantity": 0.5 }, { "cancel_order_id": "ord_01HXYZ002", "symbol": "BTC-USDC-PERP", "side": "buy", "price": 94900, "quantity": 0.3 }, { "cancel_order_id": "ord_01HXYZ003", "symbol": "BTC-USDC-PERP", "side": "sell", "price": 95100, "quantity": 0.4 } ] }' ``` ## Success Response ```json { "code": 0, "data": { "results": [ { "leg": 0, "status": "open", "cancelled_order_id": "ord_01HXYZ001", "new_order_id": "ord_01HXYZ101" }, { "leg": 1, "status": "open", "cancelled_order_id": "ord_01HXYZ002", "new_order_id": "ord_01HXYZ102" }, { "leg": 2, "status": "open", "cancelled_order_id": "ord_01HXYZ003", "new_order_id": "ord_01HXYZ103" } ] }, "timestamp": "2026-04-20T10:30:00.123Z", "request_id": "req_01HXYZ..." } ``` ## Partial Failure Legs are executed independently. If one leg's cancel target has already filled, the remaining legs continue. Failed legs report their error inline: ```json { "code": 0, "data": { "results": [ { "leg": 0, "status": "open", "cancelled_order_id": "ord_01HXYZ001", "new_order_id": "ord_01HXYZ101" }, { "leg": 1, "status": "failed", "error_code": 1400, "message": "Order not found or already filled" }, { "leg": 2, "status": "open", "cancelled_order_id": "ord_01HXYZ003", "new_order_id": "ord_01HXYZ103" } ] }, "timestamp": "2026-04-20T10:30:00.123Z", "request_id": "req_01HXYZ..." } ``` ## Rate Limiting Mass quotes have a dedicated counter and don't deduct from regular order or cancel limits. Each batch counts as 1 MPC action regardless of leg count. See [Rate Limits](https://docs.godarkdex.com/docs/rate-limits). ## Notes - Max 20 legs per batch. - All legs in a batch should target the same `symbol` for optimal MPC batching. - Available to Prime and Apex tiers only. Lower tiers receive `1429`. - Only `limit` legs with `GTC` or `GTT` are supported — see [Order Compatibility](https://docs.godarkdex.com/docs/order-compatibility). - Pre-trade risk validation applies to each replacement leg individually. --- ================================================================================ Source: https://docs.godarkdex.com/docs/ws-trading/ # WebSocket API — Connection & Trading GoDark exposes a single multiplexed WebSocket endpoint. Clients authenticate once, then send trading `op` frames and/or subscribe to channels — all on the same socket. ``` wss://api.godarkdex.com/ws/v1 ``` See the [Orders Channel](https://docs.godarkdex.com/docs/order-updates) and [Positions Channel](https://docs.godarkdex.com/docs/ws-user-events) docs for channel subscription detail. ## Message format **Client → Server** (request): ```json { "id": "c-123", "op": "order.place", "args": { /* op-specific */ } } ``` | Field | Description | | --- | --- | | `id` | Client-supplied correlation id. The server echoes it on the matching response. | | `op` | Operation name (see op reference below). | | `args` | Op-specific payload. | **Server → Client** (response to a request): ```json { "id": "c-123", "op": "order.place", "code": 0, "data": { /* ... */ } } ``` On error, `code` is non-zero and a `message` field is present. **Server → Client** (unsolicited stream event — channel push): ```json { "channel": "orders", "type": "update", "seq": 42, "data": { /* ... */ } } ``` Responses carry `id` + `op`. Stream events carry `channel` + `type` + `seq`. Never both — clients can route on the presence of `id` vs `channel`. ## Control Ops | `op` | Purpose | | --- | --- | | `login` | Authenticate the socket with a bearer token | | `logout` | Cleanly end the session | | `ping` / `pong` | Heartbeat | | `subscribe` / `unsubscribe` | Manage channel subscriptions | ### op: login Must be the **first** frame on any new connection. All other ops return `401 not_authenticated` until `login` succeeds. ```json { "id": "c-1", "op": "login", "args": { "token": "eyJhbGciOi..." } } ``` Response: ```json { "id": "c-1", "op": "login", "code": 0, "data": { "account_id": "acct_01HXYZ", "session_id": "sess_01HXYZ", "token_expires_at": "2026-04-20T10:45:00Z", "cancel_on_disconnect": false } } ``` #### Re-login / Token Refresh Send a fresh `op: login` before `token_expires_at` to rotate the token in place without dropping subscriptions. The server also emits an `auth_expired` event ~60s before expiry as a reminder. #### Cancel-on-Disconnect Opt in when logging in to have all your resting orders auto-cancelled if the socket drops: ```json { "id": "c-1", "op": "login", "args": { "token": "...", "cancel_on_disconnect": true } } ``` ### op: logout ```json { "id": "c-9", "op": "logout" } ``` Server responds with `code: 0` and closes the socket. ### op: ping / pong Client pings: ```json { "id": "c-hb-1", "op": "ping" } ``` Server responds: ```json { "id": "c-hb-1", "op": "pong", "code": 0, "data": { "server_time_ns": 1839975000123000000 } } ``` The server also pings the client every 20s; clients should reply with `pong` (same shape, client as sender) within 10s or the server will close the socket. ### op: subscribe / unsubscribe ```json { "id": "c-2", "op": "subscribe", "args": { "channel": "orders" } } ``` ```json { "id": "c-3", "op": "unsubscribe", "args": { "channel": "orders" } } ``` Channel reference: | Channel | Scope | Auth | | --- | --- | --- | | `orders` | Authenticated account | Bearer (via `op: login`) | | `positions` | Authenticated account | Bearer (via `op: login`) | | `instruments` | Public | Not required | | `transparency` | Public | Not required | ## Account Ops ### op: account.info Fetch balance, VIP tier, and account-level config. Mirrors `GET /account` — same response body. See [Account Info](https://docs.godarkdex.com/docs/account-info) for the full schema. ```json { "id": "c-20", "op": "account.info" } ``` ## Trading Ops All trading ops mirror the REST endpoints exactly — same request body, same validation, same response data. Sharing order-management code between REST and WS is a non-goal for the server but a free win for the client. ### op: order.place ```json { "id": "c-10", "op": "order.place", "args": { "symbol": "BTC-USDC-PERP", "side": "buy", "type": "limit", "quantity": 0.1, "price": 95000, "time_in_force": "GTC", "client_order_id": "my-order-001" } } ``` Response: ```json { "id": "c-10", "op": "order.place", "code": 0, "data": { "order_id": "ord_01HXYZ12345", "client_order_id": "my-order-001", "status": "NEW" } } ``` See [Place Order](https://docs.godarkdex.com/docs/place-order) for the full request schema and risk-check semantics. ### op: order.cancel Either `order_id` or `client_order_id` — exactly one. ```json { "id": "c-11", "op": "order.cancel", "args": { "order_id": "ord_01HXYZ12345" } } ``` ### op: order.modify ```json { "id": "c-12", "op": "order.modify", "args": { "order_id": "ord_01HXYZ12345", "price": 96000, "quantity": 0.15 } } ``` Queue-priority rules are identical to REST — see [Modify Order](https://docs.godarkdex.com/docs/modify-order). ## Sequence Numbers and Gap Recovery Every channel emits a monotonically increasing `seq` per subscription per session. Clients should track the last `seq` they processed and, on any gap, unsubscribe + resubscribe to receive a fresh snapshot. Full protocol detail lives on each channel's page. ## JavaScript Example ```javascript const ws = new WebSocket('wss://api.godarkdex.com/ws/v1'); let id = 0; const next = () => `c-${++id}`; ws.onopen = () => { ws.send(JSON.stringify({ id: next(), op: 'login', args: { token: ACCESS_TOKEN } })); }; ws.onmessage = (event) => { const msg = JSON.parse(event.data); if (msg.id && msg.op === 'login' && msg.code === 0) { ws.send(JSON.stringify({ id: next(), op: 'subscribe', args: { channel: 'orders' } })); ws.send(JSON.stringify({ id: next(), op: 'order.place', args: { symbol: 'BTC-USDC-PERP', side: 'buy', type: 'limit', quantity: 0.1, price: 95000, time_in_force: 'GTC', client_order_id: 'my-order-001', }, })); } if (msg.channel === 'orders') { console.log('orders event', msg.type, msg.seq, msg.data); } }; setInterval(() => ws.send(JSON.stringify({ id: next(), op: 'ping' })), 20000); ``` ## REST vs WebSocket | Aspect | REST | WebSocket | | --- | --- | --- | | Latency | Higher (TLS + HTTP per request) | Lower (persistent multiplexed socket) | | Auth | Bearer header per request | One `op: login` per session | | Streaming | `GET` snapshots only | Snapshot + incremental updates on channels | | Best for | One-off calls, cold starts | Long-running trading clients | Rate limits are shared with REST (see [Rate Limits](https://docs.godarkdex.com/docs/rate-limits)). --- ================================================================================ Source: https://docs.godarkdex.com/docs/order-updates/ # WebSocket API — Orders Channel Live order lifecycle events for the authenticated account. Subscribe once; the server sends a snapshot of all live orders, then a stream of incremental updates. ``` wss://api.godarkdex.com/ws/v1 ``` Authenticate with `op: login` first (see [WebSocket Trading](https://docs.godarkdex.com/docs/ws-trading)). ## Subscribe ```json { "id": "c-2", "op": "subscribe", "args": { "channel": "orders" } } ``` Response: ```json { "id": "c-2", "op": "subscribe", "code": 0, "data": { "channel": "orders", "seq_start": 1 } } ``` ## Event Flow ``` snapshot → snapshot → ... → snapshot (snapshot_complete: true) → update → update → ... ``` The server first replays every currently live order as a `snapshot` frame, then emits `update` frames as state changes. The final snapshot frame carries `snapshot_complete: true`; that is the signal to start applying buffered updates. Incremental updates that arrive while snapshot delivery is in progress should be **buffered** and replayed after `snapshot_complete: true`. ## Frame Shape Every frame on this channel: ```json { "channel": "orders", "type": "snapshot" | "update", "seq": 42, "snapshot_complete": false, "data": { /* order object — fields below */ } } ``` | Field | Description | | --- | --- | | `type` | `snapshot` during initial replay; `update` afterward | | `seq` | Monotonic per subscription per session. Gaps mean a missed event. | | `snapshot_complete` | `true` on the final snapshot frame; `false` on all others | | `data` | The order object — see field reference below | ## Order Object Same schema as `GET /orders/{orderId}`, plus a `message_type` that classifies the event: | `message_type` | Triggered when | | --- | --- | | `open` | Order accepted and working in the book | | `partial_fill` | Order partially filled; remainder working | | `filled` | Order fully filled | | `cancelled` | Order cancelled (see `cancel_reason`) | | `rejected` | Order rejected (see `reject_reason`) | | `modified` | Modify applied | | `cancel_rejected` | Cancel request failed (e.g. order no longer live) | | `modify_rejected` | Modify request failed | ### Example — `update` / `filled` ```json { "channel": "orders", "type": "update", "seq": 128, "snapshot_complete": false, "data": { "message_type": "filled", "order_id": "ord_01HXYZ12345", "client_order_id": "my-order-001", "symbol": "BTC-USDC-PERP", "side": "buy", "type": "limit", "time_in_force": "GTC", "price": 95000, "quantity": 0.1, "filled_quantity": 0.1, "remaining_quantity": 0, "average_fill_price": 94998.5, "last_fill_qty": 0.07, "last_fill_price": 94998.0, "status": "FILLED", "in_time_ns": 1839975000775731091, "out_time_ns": 1839975000799293016, "cancel_reason": null, "reject_reason": null } } ``` ### Field Reference | Field | Type | Description | | --- | --- | --- | | `message_type` | string | See table above | | `order_id` | string | Venue order id | | `client_order_id` | string \| null | Idempotency key set on placement | | `symbol` | string | Instrument id | | `side` | string | `buy` or `sell` | | `type` | string | `market`, `limit`, or `peg` | | `time_in_force` | string | `GTC`, `GTT`, `IOC`, or `FOK` | | `price` | number \| null | Limit price | | `quantity` | number | Original order size | | `filled_quantity` | number | Total filled so far | | `remaining_quantity` | number | Unfilled remainder | | `average_fill_price` | number \| null | Volume-weighted average | | `last_fill_qty` | number \| null | Size of the fill in this event | | `last_fill_price` | number \| null | Price of the fill in this event | | `status` | string | `NEW`, `PARTIALLY_FILLED`, `FILLED`, `CANCELLED`, `REJECTED` | | `in_time_ns` | integer | Order entry timestamp (ns epoch) | | `out_time_ns` | integer | Event emit timestamp (ns epoch) | | `cancel_reason` | string \| null | Populated on `cancelled`; see below | | `reject_reason` | string \| null | Populated on `rejected` / `cancel_rejected` / `modify_rejected`; see below | ## Rejection Reasons Values for `reject_reason` when `message_type` is `rejected`: | Value | Description | | --- | --- | | `MARGIN_INSUFFICIENT` | Pre-trade margin check failed | | `POSITION_LIMIT_EXCEEDED` | Would exceed max position size | | `LEVERAGE_EXCEEDED` | Requested leverage above instrument max | | `INSUFFICIENT_LIQUIDITY` | FOK order could not be fully filled | | `INVALID_PRICE` | Price outside acceptable range | | `DUPLICATE_CLIENT_ORDER_ID` | Another live order uses this `client_order_id` | | `INSTRUMENT_HALTED` | Instrument not currently accepting orders | | `ACCOUNT_IN_LIQUIDATION` | Account is being liquidated; new orders blocked | | `RISK_CHECK_FAILED` | Generic risk check failure | ## Cancellation Reasons Values for `cancel_reason` when `message_type` is `cancelled`: | Value | Description | | --- | --- | | `USER_REQUESTED` | Cancelled by user via REST or WS | | `IOC_REMAINDER` | Unfilled portion of an IOC order | | `FOK_NOT_FILLED` | FOK order could not fully fill | | `GTT_EXPIRED` | Reached `expiry_time` | | `SELF_TRADE_PREVENTION` | Would have matched against the same account | | `LIQUIDATION` | Account entered liquidation | | `CANCEL_ON_DISCONNECT` | Socket disconnected with `cancel_on_disconnect: true` | | `SYSTEM_CANCEL` | Cancelled by the system (settlement, cluster migration, etc.) | ## Gap Recovery Clients should track `seq`. If a gap appears (`seq_n > seq_{n-1} + 1`): 1. `op: unsubscribe` `{ channel: "orders" }` 2. `op: subscribe` `{ channel: "orders" }` — receive a fresh snapshot 3. Resume applying updates from the new `seq` series ## Unsubscribe ```json { "id": "c-9", "op": "unsubscribe", "args": { "channel": "orders" } } ``` --- ================================================================================ Source: https://docs.godarkdex.com/docs/ws-user-events/ # WebSocket API — Positions Channel Live position updates for the authenticated account. Sends a snapshot of every open position on subscribe, then incremental updates as positions change — fills, mark-price moves, funding accruals, liquidations. ``` wss://api.godarkdex.com/ws/v1 ``` Authenticate with `op: login` first (see [WebSocket Trading](https://docs.godarkdex.com/docs/ws-trading)). ## Subscribe ```json { "id": "c-4", "op": "subscribe", "args": { "channel": "positions" } } ``` Response: ```json { "id": "c-4", "op": "subscribe", "code": 0, "data": { "channel": "positions", "seq_start": 1 } } ``` ## Event Flow Identical pattern to the [Orders Channel](https://docs.godarkdex.com/docs/order-updates): ``` snapshot → snapshot → ... → snapshot (snapshot_complete: true) → update → update → ... ``` The final snapshot frame carries `snapshot_complete: true`. Updates arriving during snapshot delivery should be buffered and replayed after. ## Frame Shape ```json { "channel": "positions", "type": "snapshot" | "update", "seq": 42, "snapshot_complete": false, "data": { /* position object — fields below */ } } ``` | Field | Description | | --- | --- | | `type` | `snapshot` during initial replay; `update` afterward | | `seq` | Monotonic per subscription per session | | `snapshot_complete` | `true` on the final snapshot frame | | `data` | Position object — schema matches `GET /positions` plus `update_reason` | ## Position Object ```json { "channel": "positions", "type": "update", "seq": 214, "snapshot_complete": false, "data": { "update_reason": "fill", "position_id": "pos_01HXYZ", "symbol": "BTC-USDC-PERP", "side": "long", "size": 0.5, "entry_price": 95000.0, "mark_price": 95500.0, "margin": 4750.0, "leverage": 5, "unrealized_pnl": 250.0, "realized_pnl": 0, "funding_accrued": -12.5, "liquidation_price": 85500.0, "status": "OPEN", "updated_at": "2026-04-20T11:00:00.456Z" } } ``` ### `update_reason` Values | Value | Description | | --- | --- | | `fill` | Position changed due to an order fill | | `mark_price` | Mark price moved (PnL / liquidation price recomputed) | | `funding` | Funding rate accrued to the position | | `liquidation` | Position partially or fully liquidated | | `closed` | Position closed (size reached 0) | | `settlement` | Realized PnL settled to the vault | The server throttles `mark_price` updates to at most once per second per position to avoid flooding slow clients; other reasons are emitted immediately. For margin health tiers, partial liquidation, and how `liquidation_price` is derived, see [Margin & Liquidation](https://docs.godarkdex.com/docs/margin-and-liquidation). ### Field Reference Same semantics as [`GET /positions`](https://docs.godarkdex.com/docs/positions) — see that page for the authoritative field reference. ## Gap Recovery Clients should track `seq`. On a gap: 1. `op: unsubscribe` `{ channel: "positions" }` 2. `op: subscribe` `{ channel: "positions" }` — receive a fresh snapshot 3. Resume applying updates from the new `seq` series ## Unsubscribe ```json { "id": "c-9", "op": "unsubscribe", "args": { "channel": "positions" } } ``` --- ================================================================================ Source: https://docs.godarkdex.com/docs/order-types/ # Order Types Three order types are supported: `market`, `limit`, and `peg`. Pegged orders use a single `type=peg` with a `peg_reference` that selects which reference price to track. ## Summary | Type | Price field | Reference tracking | Typical TIF | | --- | --- | --- | --- | | `market` | Optional (acts as a cap) | — | `IOC` or `FOK` | | `limit` | Required | — | `GTC`, `GTT`, `IOC`, `FOK` | | `peg` | Not accepted | `peg_reference: mid \| bid \| ask` | `GTC`, `GTT`, `IOC` | See [Order Compatibility](https://docs.godarkdex.com/docs/order-compatibility) for the full matrix. ## Market Executes immediately at the best available prices. Walks the book until the order is filled or liquidity is exhausted. ```json { "symbol": "BTC-USDC-PERP", "side": "buy", "type": "market", "quantity": 0.1, "time_in_force": "IOC" } ``` If `price` is supplied on a market order, it acts as a **price cap** — the order will stop walking the book at that level rather than paying worse. ## Limit Executes at the specified price or better. Unfilled remainder rests in the book until matched, cancelled, or expired (per `time_in_force`). ```json { "symbol": "BTC-USDC-PERP", "side": "buy", "type": "limit", "quantity": 0.1, "price": 95000, "time_in_force": "GTC" } ``` ## Peg Tracks a reference price chosen at placement time and automatically reprices as that reference moves. See [Pegged Orders](https://docs.godarkdex.com/docs/pegged-orders) for detail on repricing semantics and `peg_reference` values. ```json { "symbol": "BTC-USDC-PERP", "side": "buy", "type": "peg", "peg_reference": "mid", "quantity": 0.1, "time_in_force": "GTC" } ``` `price` is not accepted on a `peg` order — the effective price is derived at match time from `peg_reference`. --- ================================================================================ Source: https://docs.godarkdex.com/docs/time-in-force/ # Time in Force `time_in_force` (TIF) controls how long an order is eligible to execute before it expires or is cancelled. ## Available Options | TIF | Description | | --- | --- | | `GTC` | Good Till Cancelled — rests in the book until filled or manually cancelled. | | `GTT` | Good Till Time — rests until `expiry_time` (nanosecond epoch) and is then auto-cancelled. | | `IOC` | Immediate or Cancel — fills what it can immediately; cancels the unfilled remainder. | | `FOK` | Fill or Kill — must fill completely and immediately, or the entire order is cancelled with no fills. | `GTT` replaces the earlier `GTD` naming — they are the same semantics. ## GTC ```json { "symbol": "BTC-USDC-PERP", "side": "buy", "type": "limit", "quantity": 0.1, "price": 95000, "time_in_force": "GTC" } ``` ## GTT Requires `expiry_time` as a nanosecond epoch timestamp. ```json { "symbol": "BTC-USDC-PERP", "side": "buy", "type": "limit", "quantity": 0.1, "price": 95000, "time_in_force": "GTT", "expiry_time": 1839975000000000000 } ``` Expiry is enforced at matching time — an order will not fill after `expiry_time` even if a match was otherwise possible. Expired orders emit a `cancelled` event with `cancel_reason: "GTT_EXPIRED"` (see [Orders Channel](https://docs.godarkdex.com/docs/order-updates#cancellation-reasons)). ## IOC Best paired with `market` and aggressive `limit` orders. ```json { "symbol": "BTC-USDC-PERP", "side": "buy", "type": "market", "quantity": 0.1, "time_in_force": "IOC" } ``` Unfilled remainder is auto-cancelled with `cancel_reason: "IOC_REMAINDER"`. ## FOK Use when partial fills are unacceptable. ```json { "symbol": "BTC-USDC-PERP", "side": "buy", "type": "limit", "quantity": 0.1, "price": 95000, "time_in_force": "FOK" } ``` If the full size cannot be filled immediately, the order is rejected (no fills occur) with `reject_reason: "INSUFFICIENT_LIQUIDITY"`. ## TIF vs Execution Attributes `time_in_force` controls **when** an order is eligible. It is distinct from [Execution Attributes](https://docs.godarkdex.com/docs/execution-attributes) (`aon`, `min_fill_size`), which control **how** each fill is constrained. --- ================================================================================ Source: https://docs.godarkdex.com/docs/execution-attributes/ # Execution Attributes Execution attributes are fill-level constraints applied at match time. They control **how** each individual execution is sized. This is distinct from [Time in Force](https://docs.godarkdex.com/docs/time-in-force), which controls **how long** an order is eligible to execute. ## All or None (AON) When `aon: true`, the order must be completely filled in a single match or it continues to rest. No partial fills are allowed. ```json { "symbol": "BTC-USDC-PERP", "side": "buy", "type": "limit", "quantity": 1.0, "price": 95000, "time_in_force": "GTC", "aon": true } ``` Use AON when executing the full size in one fill matters more than speed of execution. AON orders can rest indefinitely (with `GTC`) waiting for a counterparty large enough to fill them in one match. ## Minimum Fill Size `min_fill_size` requires every individual fill to meet or exceed the specified size. The order can still fill across multiple executions, but none of those executions can be smaller than the minimum. ```json { "symbol": "BTC-USDC-PERP", "side": "buy", "type": "limit", "quantity": 1.0, "price": 95000, "time_in_force": "GTC", "min_fill_size": 0.1 } ``` Use `min_fill_size` to prevent dust fills that fragment a position across many small trades. `min_fill_size` must be ≤ `quantity` and a multiple of the instrument's `step_size`. ## AON vs min_fill_size | Constraint | Effect | | --- | --- | | `aon: true` | Exactly one fill, for the full `quantity` | | `min_fill_size: X` | One or more fills, each ≥ `X` | They are mutually exclusive — supplying both returns `400 invalid_request`. --- ================================================================================ Source: https://docs.godarkdex.com/docs/pegged-orders/ # Pegged Orders A pegged order (`type: "peg"`) tracks a reference price and automatically reprices when that reference moves. Instead of placing a `limit` at a fixed price and manually adjusting it as the market shifts, a peg follows the market for you. ## Peg References Pegged orders use a single type with a `peg_reference` field: | `peg_reference` | Tracks | Typical use | | --- | --- | --- | | `mid` | Midpoint of best bid and best ask | Resting inside the spread to capture price improvement on both sides | | `bid` | Current best bid | Passive liquidity on the bid, tracking the top of book | | `ask` | Current best ask | Passive liquidity on the ask, tracking the top of book | ## How It Works When the reference price changes (e.g. a new best bid arrives), the matching engine reprices all pegged orders tied to that reference. Repricing happens within the MPC matching cycle — the same latency as any other order operation. A `peg` order does **not** accept a `price` field. The effective price is derived from the reference at match time. Pegged orders compose with `time_in_force` and `aon` the same way `limit` orders do: a `mid`-pegged GTC order rests indefinitely and reprices on every midpoint move; a `mid`-pegged IOC attempts an immediate fill at the current midpoint and cancels any unfilled remainder. ## Example — Peg to Mid ```json { "symbol": "BTC-USDC-PERP", "side": "buy", "type": "peg", "peg_reference": "mid", "quantity": 0.1, "time_in_force": "GTC" } ``` ## Example — Peg to Bid (Passive) A buy order pegged to the bid sits at the front of the queue on the buy side without ever crossing the spread: ```json { "symbol": "BTC-USDC-PERP", "side": "buy", "type": "peg", "peg_reference": "bid", "quantity": 0.1, "time_in_force": "GTC" } ``` ## Modifying Pegged Orders `PATCH /orders/{orderId}` accepts `quantity` changes on pegged orders but not `price` — the effective price is fixed by `peg_reference`. To change reference tracking, cancel and re-place. See [Order Compatibility](https://docs.godarkdex.com/docs/order-compatibility) for supported TIF and attribute combinations. --- ================================================================================ Source: https://docs.godarkdex.com/docs/order-compatibility/ # Order Compatibility This matrix shows which `type` × `time_in_force` × execution-attribute combinations are supported. ## Type × Time in Force | Type | GTC | GTT | IOC | FOK | | --- | --- | --- | --- | --- | | `market` | — | — | ✓ | ✓ | | `limit` | ✓ | ✓ | ✓ | ✓ | | `peg` | ✓ | ✓ | ✓ | — | - `market` requires an immediate TIF (`IOC` or `FOK`). Using `GTC`/`GTT` returns `400 invalid_request`. - `peg` does not support `FOK`: a pegged order's price is only meaningful at match time, so "fill now at the reference or kill" is ambiguous and disallowed. ## Type × Execution Attributes | Type | `aon` | `min_fill_size` | | --- | --- | --- | | `market` | — | ✓ | | `limit` | ✓ | ✓ | | `peg` | ✓ | — | - `aon` and `min_fill_size` are mutually exclusive on any order (see [Execution Attributes](https://docs.godarkdex.com/docs/execution-attributes)). - `market` orders do not support `aon` — they always execute as much as possible immediately. - `peg` orders do not support `min_fill_size` (prevents edge cases where the reference moves mid-match). ## Type × Price Field | Type | `price` | `peg_reference` | | --- | --- | --- | | `market` | Optional (acts as price cap) | Not accepted | | `limit` | Required | Not accepted | | `peg` | Not accepted | Required (`mid` / `bid` / `ask`) | ## Modifiability | Type | `PATCH /orders/{id}` accepts | | --- | --- | | `market` | Not modifiable (always immediate) | | `limit` | `price` and/or `quantity` | | `peg` | `quantity` only (price is derived from `peg_reference`) | See [Modify Order](https://docs.godarkdex.com/docs/modify-order) for queue-priority implications. ## Mass Quote [Mass Quote](https://docs.godarkdex.com/docs/mass-quote) legs must be `limit` orders with `GTC` or `GTT`. `market`, `peg`, and AON legs are rejected. --- ================================================================================ Source: https://docs.godarkdex.com/docs/trade-protection-rules/ # Trade Protection Rules The matching engine enforces rate limits, minimum notional requirements, and other trade protections. ## Protection Rules | Protection | Rule | Error Code | | --- | --- | --- | | Rate limiting | Weighted action rate per symbol (see below). | `1429` | | Minimum notional | Minimum order size according to fee tier. | `1430` | | Quote rest | Minimum time between price-improving modifications. | `1430` | | Self-trade prevention | Orders from the same account do not match each other. | — | ## Rate Limiting — Weighted Action Costs Not all operations consume equal MPC capacity. GoDark uses a weighted action cost model that reflects the actual computational cost of each operation: | Action | MPC Weight | Minimum Interval | Description | | --- | --- | --- | --- | | Order placement | 1.0 | 1ms per symbol | Full MPC binary search for sorted insertion | | Cancel | 0.2 | 200μs per symbol | Position-indexed lookup skips binary search | | Modify | 1.2 | 1ms per symbol | Cancel (0.2) + insert (1.0) | | Mass quote (batch) | 1.0 per batch | 1ms per symbol | Fused MPC rounds regardless of leg count | This weighted model allows significantly higher cancel throughput compared to a flat action rate. Market makers, who typically cancel 10-50x more than they place, benefit from the reduced cancel cost. ## Minimum Notional Each order must have a notional value specified in the fee tier. Calculate notional as: ``` notional = quantity × price ``` ## Quote Rest Period After modifying a price, you must wait 1 millisecond before making another price-improving modification on the same order. ## Self-Trade Prevention Orders from the same account never match each other. This prevents accidental wash trading and ensures all executions are against different counterparties. --- ================================================================================ Source: https://docs.godarkdex.com/docs/error-codes/ # Error Codes All REST responses share the same shape: `{ "code": N, "data": { ... }, "timestamp": "...", "request_id": "..." }`. On error, `data` is replaced by `message`. See [Base URLs](https://docs.godarkdex.com/docs/base-urls#response-format). ## Error Code Reference | Code | HTTP | Category | Description | | --- | --- | --- | --- | | `0` | `200` | Success | Operation completed successfully | | `1000` | `401` | Auth | `invalid_request` — malformed auth request | | `1001` | `401` | Auth | `invalid_client` — unknown `client_id`, bad `client_secret`, or bad `passphrase` | | `1002` | `401` | Auth | `token_expired` — bearer token past its `expires_in` window | | `1003` | `401` | Auth | `token_revoked` — bearer token was revoked | | `1004` | `401` | Auth | `not_authenticated` — missing `Authorization` header | | `1005` | `400` | Auth | `unsupported_grant_type` — only `client_credentials` is supported | | `1006` | `403` | Auth | `insufficient_scope` — token lacks required scope | | `1100` | `500` | System | Internal server error | | `1101` | `400` | System | Invalid JSON format | | `1102` | `415` | System | Invalid or missing `Content-Type` | | `1200` | `409` | Account | Account already exists | | `1201` | `404` | Account | Account not found | | `1300` | `500` | Database | Database operation failed | | `1301` | `409` | Database | Database constraint violation | | `1400` | `404` | Trading | Order not found or in a terminal state | | `1401` | `403` | Trading | Order belongs to a different account | | `1402` | `400` | Trading | Order type does not support the requested operation | | `1403` | `400` | Validation | Missing or invalid required fields | | `1404` | `409` | Trading | `duplicate_client_order_id` — `client_order_id` collides with another live order | | `1405` | `503` | Trading | Book full — per-symbol order book capacity reached | | `1406` | `400` | Trading | No counterparty available | | `1407` | `400` | Trading | Insufficient liquidity — FOK order cannot be fully filled | | `1410` | `400` | Risk | Margin insufficient | | `1411` | `400` | Risk | Position limit exceeded | | `1412` | `400` | Risk | Account in liquidation; new orders blocked | | `1413` | `400` | Risk | Requested leverage above instrument `max_leverage` | | `1414` | `410` | Risk | `instrument_halted` — instrument not currently accepting orders | | `1429` | `429` | Rate Limit | Rate limit exceeded — see [Rate Limits](https://docs.godarkdex.com/docs/rate-limits) | | `1430` | `400` | Trade Rules | Trade rule violation (minimum notional, quote rest period) | | `1500` | `500` | System | Unexpected internal server error | | `1501` | `503` | System | Service unavailable | | `1502` | `202` | System | Service degraded — order queued; higher latency expected | | `1503` | `503` | System | Temporarily unavailable — matching engine paused, retry later | ## HTTP Status Codes | Status | Description | | --- | --- | | `200` | Success | | `202` | Accepted — request queued (see [System Status](https://docs.godarkdex.com/docs/system-status)) | | `204` | No content (e.g. successful token revoke) | | `304` | Not Modified (conditional `GET`, see [Get Instruments](https://docs.godarkdex.com/docs/get-instruments#cache-semantics)) | | `400` | Bad request | | `401` | Unauthorized | | `403` | Forbidden | | `404` | Not found | | `409` | Conflict (idempotency / constraint) | | `410` | Gone / halted (instrument status) | | `415` | Unsupported media type | | `429` | Rate limited | | `500` | Server error | | `503` | Service unavailable | ## Error Response Example ```json { "code": 1410, "message": "Margin insufficient: available 1200.00 USDC, required 5000.00 USDC", "timestamp": "2026-04-20T10:30:00.123Z", "request_id": "req_01HXYZ..." } ``` ## Handling Errors 1. Inspect `code` — HTTP status is a coarse hint, `code` is the authoritative classifier. 2. **Auth (`1000`–`1006`)** — refresh the bearer via `POST /auth/token`, then retry. 3. **Validation (`1403`, `1101`–`1102`)** — fix the request; retries will keep failing. 4. **Trading (`1400`–`1407`, `1414`)** — inspect `message`; `1404` means use a fresh `client_order_id`; `1407` means switch from FOK to IOC or reduce size. 5. **Risk (`1410`–`1413`)** — check margin and position state via [`GET /positions`](https://docs.godarkdex.com/docs/positions) before retrying. See [Margin & Liquidation](https://docs.godarkdex.com/docs/margin-and-liquidation) and [Pre-Trade Risk Validation](https://docs.godarkdex.com/docs/place-order#pre-trade-risk-validation). 6. **Rate limit (`1429`)** — back off exponentially; rate-limit headers (`X-RateLimit-Remaining`, `X-RateLimit-Reset`) tell you when to retry. 7. **Degraded (`1502`)** — your order is queued; do **not** resubmit. 8. **System (`1500`–`1501`, `1503`)** — retry with exponential backoff starting at 1s. --- ================================================================================ Source: https://docs.godarkdex.com/docs/rate-limits/ # Rate Limits GoDark enforces rate limits to ensure fair access and platform stability. Limits are designed around the MPC matching engine's throughput capacity — every order placement, cancellation, and modification requires multi-round computation across the MPC committee and consumes finite cryptographic preprocessing material. Your per-account limits are tier-driven. Read the public schedule at [`GET /vip/tiers`](https://docs.godarkdex.com/docs/vip-tiers) and your current budget at [`GET /account/vip`](https://docs.godarkdex.com/docs/vip-tiers). Every REST response includes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` headers. Cancellations use position-indexed lookup, which bypasses the MPC binary search and reduces their computational cost to ~0.2x of an order placement. This allows significantly higher cancel throughput — particularly important for market makers, who typically cancel 10-50x more than they place. ## Tier Breakdown | Tier | REST req/min | REST req/sec | Burst | WS msg/sec | WS conns | WS subs | Orders/min | Cancels/min | Mass Quotes/min | Max Open | Max Open/Symbol | Requirements | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | Core | 60 | 2 | 5 | 5 | 2 | 5 | 10 | 50 | — | 15 | 5 | Email verified | | Select | 300 | 10 | 20 | 20 | 3 | 20 | 120 | 600 | — | 80 | 15 | $5M 30D volume | | Advanced | 1,200 | 40 | 100 | 100 | 5 | 100 | 480 | 2,400 | — | 300 | 40 | $10M 30D volume | | Prime | 3,000 | 100 | 200 | 300 | 10 | 300 | 1,200 | 6,000 | 120 | 1,200 | 100 | $25M 30D volume | | Apex | 6,000 | 200 | 300 | 500 | 15 | 500 | 2,400 | 12,000 | 600 | 2,500 | 200 | $50M 30D volume | **Mass Quotes** — Each mass quote batch contains up to 20 cancel-replace legs. A batch of 20 legs counts as 1 MPC action. At the Apex tier, 600 mass quotes/min with 20 legs each delivers up to 12,000 effective quote updates per minute. ## Trading Rules | Rule | Limit | Scope | | --- | --- | --- | | Order placement rate | 1 per 1 millisecond | Per symbol, per account | | Cancel rate | 1 per 200 microseconds | Per symbol, per account | | Modify rate | 1 per 1 millisecond | Per symbol, per account | | Mass quote rate | 1 per 1 millisecond | Per symbol, per account | | Quote rest | 1 millisecond between price improvements | Per symbol | | Minimum notional | Min Size according to fee tier | Per order | ## Weighted Action Costs Operations consume different amounts of MPC capacity. The system tracks MPC budget using weighted costs: | Action | MPC Weight | Rationale | | --- | --- | --- | | Order placement | 1.0 | Full O(log N) MPC binary search for sorted insertion | | Cancel | 0.2 | Position-indexed lookup — skips binary search | | Modify | 1.2 | Cancel (0.2) + new insertion (1.0) | | Mass quote (per batch) | 1.0 | Fused MPC rounds — constant round count regardless of leg count | ## System-Wide Limits The system enforces global throughput caps to protect the MPC matching engine from aggregate overload. These caps scale with the number of MPC committees via symbol-level sharding: | Rule | Single Committee | 2 Committees | 4 Committees | Error Code | | --- | --- | --- | --- | --- | | Global throughput cap | 10,000 actions/sec | 20,000 actions/sec | 40,000 actions/sec | `1503` | | Per-symbol throughput cap | 5,000 actions/sec | 5,000 actions/sec | 5,000 actions/sec | `1502` | | Per-symbol max book depth | 100,000 open orders | 100,000 open orders | 100,000 open orders | `1405` | Each MPC committee handles a group of symbols independently. Adding committees linearly scales total system capacity while per-symbol limits remain constant. When a system-wide or per-symbol cap is reached, additional orders are either queued (code `1502`) or rejected (code `1503`). See [System Status](https://docs.godarkdex.com/docs/system-status) for details on queuing behavior. ## Best Practices 1. Space orders at least 1ms apart and cancels at least 200μs apart per symbol. 2. Use mass quotes for multi-level quote updates — a batch of 20 legs costs the same as a single order. 3. Implement exponential backoff when receiving code `1429`. 4. Aggregate small orders to meet the minimum trade size for the fee tier. 5. Use different symbols simultaneously — limits are per-symbol. 6. Track your request timestamps per symbol to stay within limits. 7. If you receive code `1502` (queued), do not resubmit — your order will be processed. 8. If you receive code `1503` (system at capacity), retry with exponential backoff starting at 1 second. ## Rate Limit Response When rate-limited, you'll receive `429 Too Many Requests` with: ```json { "code": 1429, "message": "Rate limit exceeded. Try again in 1ms.", "timestamp": "2026-04-20T10:30:00.123Z", "request_id": "req_01HXYZ..." } ``` along with: ```http X-RateLimit-Limit: 1200 X-RateLimit-Remaining: 0 X-RateLimit-Reset: 1839975060 Retry-After: 1 ``` --- ================================================================================ Source: https://docs.godarkdex.com/docs/system-status/ # System Status Under normal operation, GoDark processes orders in sub-millisecond latency. In rare situations the system may enter a temporarily degraded state where orders are queued rather than processed immediately. ## When Degradation Occurs | Scenario | Typical Duration | What Happens | | --- | --- | --- | | Cluster migration | ~20–50ms | The MPC committee migrates to a new datacenter cluster. In-flight orders are held and processed once the new cluster is active. | | Node recovery | Seconds | One or more MPC nodes are recovering from a fault. The system continues operating (3-of-5 threshold) but may queue orders briefly if recovery affects throughput. | | Resource constraints | Seconds to minutes | Internal cryptographic preprocessing resources are temporarily exhausted. Orders are queued until resources are replenished. | ## How It Manifests ### REST API When the system is degraded, order placement returns HTTP `202 Accepted` (instead of `200`) with error code `1502`: ```json { "success": true, "code": 1502, "data": { "order_id": "123456789", "status": "queued" }, "message": "Order accepted and queued for processing", "timestamp": "2026-01-15T10:30:00.123Z" } ``` If the matching engine is fully paused, the response is HTTP `503` with error code `1503`: ```json { "success": false, "code": 1503, "message": "Matching engine temporarily unavailable. Retry after 1 second.", "timestamp": "2026-01-15T10:30:00.123Z" } ``` ### WebSocket WebSocket order submissions may receive a `queued` status before transitioning to `open`, `filled`, or `rejected`: ```json { "message_type": "queued", "order_id": 123456789, "account_id": "12345", "symbol": "BTC-USDC" } ``` ## Best Practices 1. **Do not resubmit** — If you receive code `1502`, your order is queued and will be processed. Resubmitting creates a duplicate. 2. **Check system health** — Use `GET /health` to check the current system status before placing orders in bulk. 3. **Handle `202` responses** — Treat `202 Accepted` as a success; the order will transition to its final state and you will receive the update via WebSocket (`/ws/orders`). 4. **Implement backoff for `1503`** — If the matching engine is fully paused, retry with exponential backoff starting at 1 second. --- ================================================================================ Source: https://docs.godarkdex.com/docs/sdks/ # SDKs Official GoDark client libraries for programmatic trading. Each SDK implements the same public API documented in [REST API](https://docs.godarkdex.com/docs/base-urls) and [WebSocket API](https://docs.godarkdex.com/docs/ws-trading) — including OAuth2 authentication, ECDH session setup, and AES-GCM encrypted order payloads. SDK distribution is currently limited to **approved integrators**. Contact GoDark for access. Public package registries (PyPI, npm, crates.io, pkg.go.dev, Maven Central) will be announced when general availability opens. ## Languages | Language | Package (planned) | Requirements | Status | | --- | --- | --- | --- | | [Python](https://docs.godarkdex.com/docs/sdks/python) | `godark` | Python 3.10+ | Beta | | [Rust](https://docs.godarkdex.com/docs/sdks/rust) | `godark` | Rust 2021, tokio | Beta | | [JavaScript / TypeScript](https://docs.godarkdex.com/docs/sdks/javascript) | `@godark/sdk` | Node.js 18+ | Beta | | [C++](https://docs.godarkdex.com/docs/sdks/cpp) | `godark` headers | C++17 | Beta | | [Go](https://docs.godarkdex.com/docs/sdks/go) | `github.com/gq-godark/gdx-go-sdk` | Go 1.22+ | Beta | | [Java](https://docs.godarkdex.com/docs/sdks/java) | `exchange.godark:godark` | JDK 17+ | Beta | ## Choose a client | Client | Transport | Best for | | --- | --- | --- | | **`GodarkRestClient`** | HTTPS (`/api/v1/*`) | REST-only bots, simpler deployments, matches [Place Order](https://docs.godarkdex.com/docs/place-order) semantics | | **`GodarkClient`** | WebSocket (`/ws/v1`) | Low-latency trading, multiplexed order + position streams | | **`MarketDataClient`** | WebSocket (`/ws/gomarket`) | External venue reference data — not GoDark's internal order book | All trading clients handle **auth token exchange**, **ECDH session setup**, and **order encryption** automatically. See [Authentication](https://docs.godarkdex.com/docs/authentication) and [Encryption & Transport](https://docs.godarkdex.com/docs/encryption) for the underlying protocol. ## Environment variables | Variable | Required | Description | | --- | --- | --- | | `GDX_API_KEY_ID` | Yes | API key id from onboarding (`client_id`) | | `GDX_API_SECRET` | Yes | API secret (`client_secret`) | | `GDX_REST_URL` | No | REST base URL. Default: `https://api.godarkdex.com` | | `GDX_EDGE_URL` / `GODARK_EDGE_URL` | No | WebSocket host origin. SDK appends `/ws/v1` automatically | | `GDX_PASSPHRASE` | No | Passphrase if your key requires it (see [Authentication](https://docs.godarkdex.com/docs/authentication)) | Local development typically uses `GDX_REST_URL=http://127.0.0.1:4000` and `GDX_EDGE_URL=ws://127.0.0.1:4000`. ## Network endpoints | Network | REST | WebSocket | | --- | --- | --- | | Mainnet | `https://api.godarkdex.com/api/v1` | `wss://api.godarkdex.com/ws/v1` | | Testnet | `https://api.godarkdex-testnet.com/api/v1` | `wss://api.godarkdex-testnet.com/ws/v1` | | Localnet | `http://127.0.0.1:4000/api/v1` | `ws://127.0.0.1:4000/ws/v1` | Pass either a bare host (`https://api.godarkdex.com`) or the full `/api/v1` / `/ws/v1` path — SDKs normalize both forms. ## REST trading flow Every SDK follows the same sequence for encrypted REST orders: 1. `POST /auth/token` — exchange `api_key_id` + `api_secret` for a 15-minute bearer token 2. `POST /session/setup` — ECDH key exchange; derive AES-256-GCM session key 3. Encrypted `POST /orders`, `DELETE /orders/{id}`, `PATCH /orders/{id}` — protobuf payloads with GCM AAD WebSocket clients perform the same auth + session setup over the multiplexed socket before `order.place` / `order.cancel` ops. ## Error handling All SDKs expose typed errors that map to [Error Codes](https://docs.godarkdex.com/docs/error-codes): | Error | Typical cause | | --- | --- | | `AuthenticationError` | Invalid or expired credentials (`1000`–`1006`) | | `SessionError` | ECDH / session setup failure | | `EncryptionError` | Encrypt/decrypt or framing error | | `OrderError` | Risk rejection or trading error (`1410`–`1413`, `1400`–`1407`) | | `TimeoutError` | Await/poll exceeded deadline | | `ConnectionError` | Network or WebSocket disconnect | ## Related documentation - [Programmatic Access](https://docs.godarkdex.com/docs/programmatic-access) — getting started with the API - [Trading Concepts](https://docs.godarkdex.com/docs/order-types) — order types, TIF, execution attributes (read before placing orders) - [Rules & Limits](https://docs.godarkdex.com/docs/trade-protection-rules) — rate limits and trade protection --- ================================================================================ Source: https://docs.godarkdex.com/docs/sdks/python/ # Python SDK Encrypted Python client for the GoDark API. Package name: **`godark`**. **Requirements:** Python 3.10+ **Status:** Beta — contact GoDark for SDK access. ## Installation Public PyPI release is not yet available. Approved integrators receive distribution instructions directly. When published: ```bash pip install godark ``` ## Quickstart Set credentials, then place a limit order over encrypted REST: ```python import asyncio import os from godark import GodarkRestClient async def main() -> None: async with GodarkRestClient( api_key_id=os.environ["GDX_API_KEY_ID"], api_secret=os.environ["GDX_API_SECRET"], ) as client: ack = await client.place_order( "BTC-USDC-PERP", "BUY", type="LIMIT", quantity=0.01, price=95000.0, time_in_force="GTC", client_order_id="my-first-order", ) print("placed", ack.order_id) asyncio.run(main()) ``` See [Place Order](https://docs.godarkdex.com/docs/place-order) for all request fields. ## Clients | Class | Description | | --- | --- | | `GodarkRestClient` | REST-only: auth → session setup → encrypted `/orders` | | `GodarkClient` | WebSocket trading + order/position streams on `/ws/v1` | | `MarketDataClient` | External venue feeds on `/ws/gomarket` | ## `GodarkRestClient` methods | Method | Docs reference | | --- | --- | | `connect()` / `disconnect()` | [Authentication](https://docs.godarkdex.com/docs/authentication), [Encryption](https://docs.godarkdex.com/docs/encryption) | | `place_order(...)` | [Place Order](https://docs.godarkdex.com/docs/place-order) | | `cancel_order(...)` | [Cancel Order](https://docs.godarkdex.com/docs/cancel-order) | | `cancel_order_by_client_id(...)` | [Cancel Order](https://docs.godarkdex.com/docs/cancel-order) | | `modify_order(...)` | [Modify Order](https://docs.godarkdex.com/docs/modify-order) | | `get_order(...)` | [Get Order](https://docs.godarkdex.com/docs/get-order) | | `get_order_by_client_id(...)` | [Get Order](https://docs.godarkdex.com/docs/get-order) | | `await_terminal_status(...)` | Poll until `FILLED`, `CANCELLED`, or `REJECTED` | ## `GodarkClient` (WebSocket) | Capability | Docs reference | | --- | --- | | `place_order`, `cancel_order`, `modify_order` | [WebSocket Trading](https://docs.godarkdex.com/docs/ws-trading) | | Order update callbacks | [Orders Channel](https://docs.godarkdex.com/docs/order-updates) | | Position update callbacks | [Positions Channel](https://docs.godarkdex.com/docs/ws-user-events) | ## Types and enums Exported from `godark`: `Side`, `OrderType`, `TimeInForce`, `OrderStatus`, `OrderAck`, `OrderUpdate`, `PositionUpdate`, and error classes (`AuthenticationError`, `SessionError`, `OrderError`, etc.). ## Bundled examples The SDK ships runnable examples including `quickstart_docs`, `full_trader_rest`, `full_trader_example`, `local_e2e`, and `market_data`. ## See also - [SDKs overview](https://docs.godarkdex.com/docs/sdks) - [Programmatic Access](https://docs.godarkdex.com/docs/programmatic-access) --- ================================================================================ Source: https://docs.godarkdex.com/docs/sdks/rust/ # Rust SDK Encrypted Rust client for the GoDark API. Crate name: **`godark`**. **Requirements:** Rust 2021, tokio **Status:** Beta — contact GoDark for SDK access. ## Installation Public crates.io release is not yet available. Approved integrators receive distribution instructions directly. When published: ```bash cargo add godark ``` ## Quickstart ```rust use godark::{GodarkRestClient, OrderType, Side, TimeInForce}; #[tokio::main] async fn main() -> Result<(), Box> { let client = GodarkRestClient::builder() .api_key_id(std::env::var("GDX_API_KEY_ID")?) .api_secret(std::env::var("GDX_API_SECRET")?) .build()?; client.connect().await?; let ack = client .place_order( "BTC-USDC-PERP", Side::Buy, OrderType::Limit, 0.01, Some(95_000.0), TimeInForce::Gtc, false, None, None, Some("my-first-order".into()), ) .await?; println!("placed {}", ack.order_id); client.disconnect().await?; Ok(()) } ``` See [Place Order](https://docs.godarkdex.com/docs/place-order) for all request fields. ## Clients | Type | Description | | --- | --- | | `GodarkRestClient` | REST-only encrypted trading | | `GodarkClient` | WebSocket trading + streams | | `MarketDataClient` | External venue feeds | Build `GodarkRestClient` with the builder pattern: `.api_key_id()`, `.api_secret()`, `.rest_base_url()`. ## `GodarkRestClient` methods | Method | Docs reference | | --- | --- | | `connect()` / `disconnect()` | [Authentication](https://docs.godarkdex.com/docs/authentication), [Encryption](https://docs.godarkdex.com/docs/encryption) | | `place_order(...)` | [Place Order](https://docs.godarkdex.com/docs/place-order) | | `cancel_order(...)` | [Cancel Order](https://docs.godarkdex.com/docs/cancel-order) | | `cancel_order_by_client_id(...)` | [Cancel Order](https://docs.godarkdex.com/docs/cancel-order) | | `modify_order(...)` | [Modify Order](https://docs.godarkdex.com/docs/modify-order) | | `get_order(...)` | [Get Order](https://docs.godarkdex.com/docs/get-order) | | `await_terminal_status(...)` | Poll until terminal order state | ## Enums `Side`, `OrderType`, `TimeInForce`, `OrderStatus`, `OrderUpdateType`, `PositionUpdateType`, `CancelReason`. ## Bundled examples Run with `cargo run --example quickstart_docs`. Also includes `full_trader_rest`, `full_trader_example`, `local_e2e`, and `market_data`. ## See also - [SDKs overview](https://docs.godarkdex.com/docs/sdks) - [Programmatic Access](https://docs.godarkdex.com/docs/programmatic-access) --- ================================================================================ Source: https://docs.godarkdex.com/docs/sdks/javascript/ # JavaScript / TypeScript SDK Encrypted JavaScript and TypeScript client for the GoDark API. Package name: **`@godark/sdk`**. **Requirements:** Node.js 18+ **Status:** Beta — contact GoDark for SDK access. ## Installation Public npm release is not yet available. Approved integrators receive distribution instructions directly. When published: ```bash npm install @godark/sdk ``` ## Quickstart ```typescript import { GodarkRestClient } from "@godark/sdk"; async function main(): Promise { const client = new GodarkRestClient({ apiKeyId: process.env.GDX_API_KEY_ID!, apiSecret: process.env.GDX_API_SECRET!, }); await client.connect(); await client.placeOrder("BTC-USDC-PERP", "BUY", { quantity: 0.01, type: "LIMIT", price: 95000, timeInForce: "GTC", clientOrderId: "my-first-order", }); await client.disconnect(); } main().catch(console.error); ``` See [Place Order](https://docs.godarkdex.com/docs/place-order) for all request fields. ## Clients | Class | Description | | --- | --- | | `GodarkRestClient` | REST-only encrypted trading | | `GodarkClient` | WebSocket trading + streams | | `MarketDataClient` | External venue feeds | The package ships ESM, CJS, and TypeScript declarations (`dist/index.js`, `dist/index.d.ts`). ## `GodarkRestClient` methods | Method | Docs reference | | --- | --- | | `connect()` / `disconnect()` | [Authentication](https://docs.godarkdex.com/docs/authentication), [Encryption](https://docs.godarkdex.com/docs/encryption) | | `placeOrder(...)` | [Place Order](https://docs.godarkdex.com/docs/place-order) | | `cancelOrder(...)` | [Cancel Order](https://docs.godarkdex.com/docs/cancel-order) | | `modifyOrder(...)` | [Modify Order](https://docs.godarkdex.com/docs/modify-order) | | `getOrder(...)` | [Get Order](https://docs.godarkdex.com/docs/get-order) | ## `GodarkClient` (WebSocket) | Capability | Docs reference | | --- | --- | | `placeOrder`, `cancelOrder`, `modifyOrder` | [WebSocket Trading](https://docs.godarkdex.com/docs/ws-trading) | | Order update stream | [Orders Channel](https://docs.godarkdex.com/docs/order-updates) | | Position update stream | [Positions Channel](https://docs.godarkdex.com/docs/ws-user-events) | ## Types Exported types include `OrderAck`, `OrderUpdate`, `PositionUpdate`, `Side`, `OrderType`, `TimeInForce`, and typed error classes. ## Bundled examples Includes `quickstart-docs.ts`, `full-trader-rest.ts`, `full-trader-example.ts`, `local_e2e.mjs`, and `market-data.ts`. ## See also - [SDKs overview](https://docs.godarkdex.com/docs/sdks) - [Programmatic Access](https://docs.godarkdex.com/docs/programmatic-access) --- ================================================================================ Source: https://docs.godarkdex.com/docs/sdks/cpp/ # C++ SDK Encrypted C++17 client for the GoDark API. Headers under **`godark/`**. **Requirements:** C++17, CMake **Status:** Beta — contact GoDark for SDK access. ## Installation Public Conan/vcpkg packages are not yet available. Approved integrators receive build instructions directly. Build from source with CMake: ```bash cmake -B build -S . cmake --build build -j ``` ## Quickstart ```cpp #include #include #include int main() { godark::GodarkRestClient::Config cfg; cfg.api_key_id = std::getenv("GDX_API_KEY_ID"); cfg.api_secret = std::getenv("GDX_API_SECRET"); godark::GodarkRestClient client{cfg}; client.connect(); auto ack = client.place_order( "BTC-USDC-PERP", godark::Side::BUY, godark::OrderType::LIMIT, 0.01, std::optional{95000.0}, godark::TimeInForce::GTC, false, std::nullopt, std::nullopt, std::optional{"my-first-order"}); std::cout << "placed " << ack.order_id << "\n"; client.disconnect(); return 0; } ``` See [Place Order](https://docs.godarkdex.com/docs/place-order) for all request fields. ## Clients | Type | Header | Description | | --- | --- | --- | | `GodarkRestClient` | `godark/rest_client.hpp` | REST-only encrypted trading | | `GodarkClient` | `godark/client.hpp` | WebSocket trading + streams | | `MarketDataClient` | `godark/market_data.hpp` | External venue feeds | Configure via `GodarkRestClient::Config`: `api_key_id`, `api_secret`, `rest_base_url`, optional `passphrase` and `symbol_overrides`. Environment variables: `GDX_API_KEY_ID`, `GDX_API_SECRET`, `GDX_REST_URL`, `GODARK_EDGE_URL` / `GDX_EDGE_URL`. ## `GodarkRestClient` methods | Method | Docs reference | | --- | --- | | `connect()` / `disconnect()` | [Authentication](https://docs.godarkdex.com/docs/authentication), [Encryption](https://docs.godarkdex.com/docs/encryption) | | `place_order(...)` | [Place Order](https://docs.godarkdex.com/docs/place-order) | | `cancel_order(...)` | [Cancel Order](https://docs.godarkdex.com/docs/cancel-order) | | `cancel_order_by_client_id(...)` | [Cancel Order](https://docs.godarkdex.com/docs/cancel-order) | | `modify_order(...)` | [Modify Order](https://docs.godarkdex.com/docs/modify-order) | | `get_order(...)` | [Get Order](https://docs.godarkdex.com/docs/get-order) | | `await_terminal_status(...)` | Poll until terminal order state | ## Bundled examples Includes `quickstart.cpp`, `full_trader_rest.cpp`, `full_trader_example.cpp`, `local_e2e.cpp`, and `market_data_example.cpp`. ## See also - [SDKs overview](https://docs.godarkdex.com/docs/sdks) - [Programmatic Access](https://docs.godarkdex.com/docs/programmatic-access) --- ================================================================================ Source: https://docs.godarkdex.com/docs/sdks/go/ # Go SDK Encrypted Go client for the GoDark API. Module: **`github.com/gq-godark/gdx-go-sdk`** (import as `godark`). **Requirements:** Go 1.22+ **Status:** Beta — contact GoDark for SDK access. ## Installation Public module proxy release is not yet available. Approved integrators receive distribution instructions directly. When published: ```bash go get github.com/gq-godark/gdx-go-sdk ``` Build from source (requires `git submodule update --init --recursive` for `gdx-proto`): ```bash go build ./... go test ./... -count=1 ``` ## Quickstart Set credentials, then place a limit order over encrypted REST: ```go package main import ( "context" "fmt" "log" "os" "github.com/gq-godark/gdx-go-sdk" ) func main() { client, err := godark.NewRestClient(godark.RestClientConfig{ APIKeyID: os.Getenv("GDX_API_KEY_ID"), APISecret: os.Getenv("GDX_API_SECRET"), Passphrase: os.Getenv("GDX_PASSPHRASE"), BaseURL: os.Getenv("GDX_REST_URL"), // optional }) if err != nil { log.Fatal(err) } ctx := context.Background() if err := client.Connect(ctx); err != nil { log.Fatal(err) } defer func() { _ = client.Disconnect(ctx) }() ack, err := client.PlaceOrder(ctx, godark.PlaceOrderRestRequest{ PlaceOrderRequest: godark.PlaceOrderRequest{ Symbol: "BTC-USDC-PERP", Side: godark.SideBuy, OrderType: godark.OrderTypeLimit, Quantity: 0.01, Price: 95000, }, ClientOrderID: "my-first-order", }) if err != nil { log.Fatal(err) } fmt.Printf("placed %s\n", ack.OrderID) } ``` See [Place Order](https://docs.godarkdex.com/docs/place-order) for all request fields. ## Clients | Type | Description | | --- | --- | | `GodarkRestClient` | REST-only: auth → session setup → encrypted `/orders` | | `GodarkClient` | WebSocket trading + order/position streams on `/ws/v1` | | `MarketDataClient` | External venue feeds on `/ws/gomarket` | Construct with `godark.NewRestClient(cfg)` or `godark.NewClient(cfg)`. ## `GodarkRestClient` methods | Method | Docs reference | | --- | --- | | `Connect(ctx)` / `Disconnect(ctx)` | [Authentication](https://docs.godarkdex.com/docs/authentication), [Encryption](https://docs.godarkdex.com/docs/encryption) | | `PlaceOrder(ctx, req)` | [Place Order](https://docs.godarkdex.com/docs/place-order) | | `CancelOrder(ctx, orderID, symbol)` | [Cancel Order](https://docs.godarkdex.com/docs/cancel-order) | | `CancelOrderByClientID(ctx, clientOrderID, symbol)` | [Cancel Order](https://docs.godarkdex.com/docs/cancel-order) | | `ModifyOrder(ctx, orderID, symbol, newPrice, newQuantity)` | [Modify Order](https://docs.godarkdex.com/docs/modify-order) | | `GetOrder(ctx, orderID)` | [Get Order](https://docs.godarkdex.com/docs/get-order) | | `GetOrderByClientID(ctx, clientOrderID)` | [Get Order](https://docs.godarkdex.com/docs/get-order) | | `GetMe(ctx)` / `GetMyBalance(ctx)` | [Account Info](https://docs.godarkdex.com/docs/account-info) | | `AwaitTerminalStatus(ctx, orderID, timeout, pollInterval)` | Poll until terminal order state | ## `GodarkClient` (WebSocket) | Capability | Docs reference | | --- | --- | | `PlaceOrder`, `CancelOrder`, `ModifyOrder` | [WebSocket Trading](https://docs.godarkdex.com/docs/ws-trading) | | `Subscribe` / `Unsubscribe` | Channel subscriptions | | `OrderUpdates()`, `PositionUpdates()` channels | [Orders Channel](https://docs.godarkdex.com/docs/order-updates), [User Events](https://docs.godarkdex.com/docs/ws-user-events) | Callbacks (`OnOrderUpdate`, etc.) run on the WebSocket receive goroutine — keep them fast or hand off to your own queue. The SDK does not auto-reconnect. ## Types and errors Exported enums: `Side`, `OrderType`, `TimeInForce`, `OrderStatus`, and related request/ack types. Error types (use `errors.As`): `AuthenticationError`, `SessionError`, `OrderError`, `EncryptionError`, `ConnectionError`, `TimeoutError`. See [Error Codes](https://docs.godarkdex.com/docs/error-codes). Environment variables accept `GDX_*` or `GODARK_*` prefixes (for example `GODARK_API_KEY_ID`, `GDX_REST_URL`). ## Bundled examples Runnable under `examples/`: `quickstart_docs`, `full_trader_rest`, `full_trader_example`, `market_data`, `e2e_trading_smoke`. ```bash go run ./examples/quickstart_docs ``` ## See also - [SDKs overview](https://docs.godarkdex.com/docs/sdks) - [Programmatic Access](https://docs.godarkdex.com/docs/programmatic-access) --- ================================================================================ Source: https://docs.godarkdex.com/docs/sdks/java/ # Java SDK Encrypted Java client for the GoDark API. Maven coordinates: **`exchange.godark:godark`**. **Requirements:** JDK 17+ **Status:** Beta — contact GoDark for SDK access. ## Installation Public Maven Central release is not yet available. Approved integrators receive distribution instructions directly. When published: ```kotlin dependencies { implementation("exchange.godark:godark:0.2.0") } ``` Build from source at the SDK root (requires `gdx-proto` submodule): ```bash ./gradlew check ./gradlew shadowJar # build/libs/godark--all.jar ``` ## Quickstart Set credentials, then place a limit order over encrypted REST: ```java import godark.GodarkRestClient; import godark.Types; public class Quickstart { public static void main(String[] args) throws Exception { GodarkRestClient client = GodarkRestClient.builder() .apiKeyId(System.getenv("GDX_API_KEY_ID")) .apiSecret(System.getenv("GDX_API_SECRET")) .passphrase(System.getenv("GDX_PASSPHRASE")) .restBaseUrl(GodarkRestClient.resolveRestBaseUrl(System.getenv("GDX_REST_URL"))) .build(); client.connect(); try { Types.OrderAck ack = client.placeOrder( "BTC-USDC-PERP", "BUY", "LIMIT", 0.01, 95000.0, "GTC", false, null, null, "my-first-order"); System.out.println("placed " + ack.orderId()); } finally { client.close(); } } } ``` See [Place Order](https://docs.godarkdex.com/docs/place-order) for all request fields. ## Clients | Class | Description | | --- | --- | | `GodarkRestClient` | REST-only encrypted trading | | `GodarkClient` | WebSocket trading + streams | | `MarketDataClient` | External venue feeds on `/ws/gomarket` | Build `GodarkRestClient` with `GodarkRestClient.builder()`: `.apiKeyId()`, `.apiSecret()`, `.passphrase()`, `.restBaseUrl()`. ## `GodarkRestClient` methods | Method | Docs reference | | --- | --- | | `connect()` / `close()` | [Authentication](https://docs.godarkdex.com/docs/authentication), [Encryption](https://docs.godarkdex.com/docs/encryption) | | `placeOrder(...)` | [Place Order](https://docs.godarkdex.com/docs/place-order) | | `cancelOrder(orderId, symbol)` | [Cancel Order](https://docs.godarkdex.com/docs/cancel-order) | | `cancelOrderByClientId(clientOrderId, symbol)` | [Cancel Order](https://docs.godarkdex.com/docs/cancel-order) | | `modifyOrder(...)` | [Modify Order](https://docs.godarkdex.com/docs/modify-order) | | `getOrder(orderId)` | [Get Order](https://docs.godarkdex.com/docs/get-order) | | `getOrderByClientOrderId(clientOrderId)` | [Get Order](https://docs.godarkdex.com/docs/get-order) | | `getMe()` / `getMyBalance()` | [Account Info](https://docs.godarkdex.com/docs/account-info) | | `awaitTerminalStatus(orderId, timeoutSec, pollIntervalSec)` | Poll until terminal order state | ## `GodarkClient` (WebSocket) | Capability | Docs reference | | --- | --- | | `placeOrder`, `cancelOrder`, `modifyOrder` | [WebSocket Trading](https://docs.godarkdex.com/docs/ws-trading) | | Order and position update handlers | [Orders Channel](https://docs.godarkdex.com/docs/order-updates), [User Events](https://docs.godarkdex.com/docs/ws-user-events) | ## Types and errors Public API lives in the `godark` package: `Enums`, `Types`, `Proto`, and exception types (`GodarkException`, `SessionException`, `OrderRejectedException`, `EncryptionException`, etc.). See [Error Codes](https://docs.godarkdex.com/docs/error-codes). Environment variables accept `GDX_*` or `GODARK_*` prefixes. Optional `.env` at the repository root is loaded by `EnvFiles` for local samples. ## Bundled examples Gradle tasks under the `examples` group: | Task | Description | | --- | --- | | `runQuickstart` | WebSocket: subscribe, place, cancel | | `runRestQuickstart` | REST: auth + one limit order | | `runMarketDataSample` | GoMarket orderbook frame | | `runTraderFlowSample` | WebSocket place, modify, cancel | ```bash ./gradlew tasks --group=examples ./gradlew runRestQuickstart ``` ## See also - [SDKs overview](https://docs.godarkdex.com/docs/sdks) - [Programmatic Access](https://docs.godarkdex.com/docs/programmatic-access) --- ================================================================================ Source: https://docs.godarkdex.com/docs/agentic-cli/ # Agent Access Let an AI agent — Cursor, Claude Desktop, Codex, Continue, a CI job, or your own script — trade on GoDark the way a person uses the web app: check a balance, read the book, place an order, watch the fills. You hand it the package and tell it to use GoDark; it discovers every tool on its own and does the heavy lifting. You don't read an endpoint reference — the agent does. The agent layer ships **inside the GoDark SDK** you receive during onboarding — same package, nothing extra to obtain. Underneath, the MCP server and the CLI both call the same SDK: one implementation of the crypto, session, and protobuf logic, reached two ways. ## What you get - **MCP server** — exposes GoDark as native tools any MCP-compatible agent can call (balance, positions, quotes, place/cancel/modify orders). This is the standard interface coding agents speak. - **`godark` CLI** — the same actions as shell commands with `--json` output and `--dry-run`, for bash, cron, or GitHub Actions. Deterministic exit codes: `0` on success, non-zero with a structured error otherwise. - **`SKILL.md`** — a single file that teaches the agent what exists, so it never has to guess or read docs. Read tools (balance, positions, quotes) are available by default. Write tools (place, cancel, modify) are opt-in — the operator enables them explicitly. ## 1. Get the SDK and build it Your SDK arrives as an archive during onboarding (for example `gdx-rust-sdk.zip` or `godark-cpp-sdk.tar.gz`). Extract it and build it following the `README.md` inside — the agent layer (the `godark` CLI and `godark-mcp` server) is included and builds alongside the SDK: ```bash tar -xzf godark-cpp-sdk.tar.gz # or: unzip gdx-rust-sdk.zip cd godark-cpp-sdk # build per the bundled README (toolchain differs by language) ``` The tools and CLI are identical in every language; only the build step and the launch command differ: | SDK | Launch the MCP server with | |-----|----------------------------| | Python | `python -m godark_mcp.server` | | JavaScript | `godark-mcp` | | Go | `godark-mcp` | | Rust | `godark-mcp` | | Java | `godark-mcp` | | C++ | `godark-mcp` | The rest of this page applies to all of them. ## 2. Set your credentials Create credentials once (frontend → fund via faucet → **Settings → API Key Management → Create API Key**), then pass them as environment variables — never commit them to a config file: ```bash export GODARK_API_KEY_ID="gdk_your_key_id" export GODARK_API_SECRET="your_api_secret" export GODARK_PASSPHRASE="your_passphrase" # Allow the agent to place/cancel/modify orders (omit for read-only) export GODARK_WRITE_ENABLED=1 ``` These can also live in a `.env` next to the SDK (`cp .env.example .env`); the OS environment always wins. See [Authentication](https://docs.godarkdex.com/docs/authentication) for how the key pair and passphrase work. ## 3. Register the MCP server with your agent Add GoDark to your agent's MCP config. The block below is the cross-tool standard — the same format Cursor (`.cursor/mcp.json`), Claude Desktop, Codex, and most coding agents read. Point it at the launch command for your SDK from the table above: ```json { "mcpServers": { "godark-trading": { "type": "stdio", "command": "godark-mcp", "env": { "GODARK_API_KEY_ID": "${env:GODARK_API_KEY_ID}", "GODARK_API_SECRET": "${env:GODARK_API_SECRET}", "GODARK_PASSPHRASE": "${env:GODARK_PASSPHRASE}", "GODARK_WRITE_ENABLED": "1" } } } } ``` That's the whole setup. Your agent now has the GoDark tools — no code to write. (For the Python SDK, set `"command": "python"` and `"args": ["-m", "godark_mcp.server"]`.) ## Let the agent discover the rest This is the point of the agent layer: you don't explain GoDark to your agent — the package does. Enable the MCP server (above), or hand the agent the `SKILL.md` that ships in the archive. Either way it reads the full tool catalog — every tool, its parameters, and the response schema — then drives them on your behalf: ```markdown --- name: godark-trading description: Trade on the GoDark dark pool. Use for checking balance, positions, quotes, leverage, and placing/cancelling/modifying orders. --- # GoDark Trading Run `godark_doctor` first to verify connectivity. Always check balance before trading. Read tools: godark_doctor, godark_get_me, godark_get_balance, godark_get_leverage, godark_get_positions, godark_get_order, godark_get_quote Write tools (require GODARK_WRITE_ENABLED=1): godark_place_order (supports dry_run), godark_cancel_order, godark_modify_order Symbols: BTC-USDC-PERP, ETH-USDC-PERP, SOL-USDC-PERP All tools return {ok: bool, data?: {...}, error?: {code, message}}. ``` You give the agent one config (or one file) and tell it to use GoDark; it reads, understands, and trades. ## Tools the agent can call Every tool — and its matching CLI command — returns the same envelope: `{ok, data?, error?: {code, message}}`. The agent parses it once. | Tool / Command | Access | Purpose | |----------------|--------|---------| | `godark_doctor` / `doctor` | read | Verify connectivity, auth, encrypted session | | `godark_get_me` / `me` | read | Profile, wallet, fee tier | | `godark_get_balance` / `balance` | read | Shielded pool balance | | `godark_get_leverage` / `leverage` | read | Per-symbol leverage settings | | `godark_get_positions` / — | read | Open positions with unrealized PnL | | `godark_get_order` / `order get` | read | Order status by ID | | `godark_get_quote` / `quote` | read | Best bid/ask and spread | | `godark_place_order` / `order place` | write | Place an order (supports `dry_run` preview) | | `godark_cancel_order` / `order cancel` | write | Cancel an open order | | `godark_modify_order` / `order modify` | write | Change price/quantity | Write tools only appear when `GODARK_WRITE_ENABLED=1`, so a read-only agent can explore safely. ## CLI usage (scripts and CI) The same actions are available as the `godark` command. Every command takes `--json` for machine-readable output: ```bash godark doctor --json # verify auth + connectivity godark balance --json # shielded pool balance godark leverage --json # per-symbol leverage godark quote BTC-USDC-PERP --json # best bid/ask (symbol is positional) # Preview an order without sending it godark order place --symbol BTC-USDC-PERP --side buy --qty 0.01 \ --type LIMIT --price 100000 --tif GTC --dry-run --json # Send it godark order place --symbol BTC-USDC-PERP --side buy --qty 0.01 \ --type LIMIT --price 100000 --tif GTC --json godark order get --json godark order cancel --json godark order modify --price 99500 --json ``` In CI, a job can run the `--dry-run` form on a pull request and the real order on merge — exit code `0` is success, non-zero is a rejection with a structured reason (insufficient margin, symbol not found, rate limit). ## Recommended agent flow 1. `godark_doctor` — confirm everything is connected 2. `godark_get_balance` — check available margin 3. `godark_get_quote` — read the current market 4. `godark_place_order` with `dry_run: true` — preview the order 5. `godark_place_order` with `dry_run: false` — submit 6. `godark_get_order` — track the fill 7. `godark_get_positions` — monitor exposure For the REST/WebSocket details these tools call underneath, see [Programmatic Access](https://docs.godarkdex.com/docs/programmatic-access). ================================================================================ Source: https://docs.godarkdex.com/docs/trade-flow/ # Trade Flow This section describes the end-to-end lifecycle of an order from submission to on-chain settlement using GoDark's MPC architecture. ## Order-to-Settlement Lifecycle ![Order Lifecycle Sequence](https://docs.godarkdex.com/images/architecture/client-order-lifecycle-sequence.png) ![Compute Network Architecture](https://docs.godarkdex.com/images/architecture/compute-network-architecture.png) ## Two-Tier Gateway Architecture ![Two-Tier Gateway Architecture](https://docs.godarkdex.com/images/architecture/client-two-tier-gateway.png) GoDark uses a two-tier gateway architecture to optimize for both latency and security: | Component | Edge Gateways | Sequencer Gateway | |-----------|---------------|-------------------| | **Location** | Deployed near traders (multiple regions) | Co-located with MPC nodes | | **Scaling** | Horizontal — scales to handle any number of connections | Single instance with hot standby | | **Role** | TLS termination, authentication, rate limiting, WebSocket management | Sequence number assignment, parallel fanout to 5 nodes | | **Order privacy at gateway** | Encrypted session framing before MPC fanout | Sequence assignment only; no MPC plaintext | Gateway encryption protects order contents from passive observers and from logs/traces. A compromised gateway is a separate trust boundary — see [Encryption & Transport](https://docs.godarkdex.com/docs/encryption). This means a trader in Tokyo connects to a local Edge Gateway with ~2ms TLS handshake (instead of 300ms to a distant datacenter), while the Sequencer Gateway focuses purely on ordering and distribution. ## Step-by-Step Flow | Step | Component | Description | |------|-----------|-------------| | **1. Order submission** | Client → Edge Gateway | Order sent via REST (`POST /dex-trading`) or WebSocket over TLS-encrypted connection. | | **2. Edge processing** | Edge Gateway | Handles authentication, rate limiting, and input validation. Order payloads are encrypted in transit before MPC fanout. | | **3. Sequencing** | Sequencer Gateway | Assigns a global sequence number, ensuring deterministic ordering, and fans the order to all 5 MPC nodes simultaneously. | | **4. Secret sharing** | MPC Committee | The MPC committee secret-shares your order, matches it against the secret-shared orderbook, updates positions, and runs margin checks — all without any single node seeing the data. See [Margin & Liquidation](https://docs.godarkdex.com/docs/margin-and-liquidation) for how margin health and liquidation tiers work. | | **5. Acknowledgment** | MPC → Client | You receive an acknowledgment once 3 of 5 nodes confirm the operation. | | **6. Trade confirmation** | MPC → Client | Fill events pushed via WebSocket `order_updates` channel (`filled`, `partially_filled`). | | **7. Batch settlement** | Settlement Relayer | Trades batched (configurable: 1–2s default). Net position deltas computed per user. 3-of-5 committee signature required. | | **8. On-chain finality** | Solana | Settlement transaction updates shielded-pool commitments and finalizes aggregate collateral state. | ================================================================================ Source: https://docs.godarkdex.com/docs/margin-and-liquidation/ # Margin & Liquidation GoDark uses **isolated margin**: each open position carries its own collateral silo. The sequencer continuously evaluates margin health and applies a **six-tier ladder** — from early warnings through partial liquidations — before escalating to auto-deleveraging (ADL) or insurance-fund backstop. This page describes how margin requirements, health tiers, and liquidation work. For fee tiers (Core → Apex), see [VIP Tiers](https://docs.godarkdex.com/docs/vip-tiers) — those are unrelated to margin health. ## Isolated Margin Model | Concept | Description | | --- | --- | | **Initial margin (IM)** | Collateral locked when a position opens: `⌈size × price / leverage⌉` | | **Extra margin** | Optional additional collateral added to a position | | **Equity** | IM + extra margin + unrealized PnL | | **Maintenance margin** | Minimum equity required to keep the position open: `size × mark × maintenance_rate` | | **Margin ratio** | `equity / maintenance_margin` — values below 100% trigger liquidation | Positions do **not** share collateral across markets. Higher leverage requires less initial margin but leaves a tighter buffer before liquidation. Default platform rates (overridable per instrument via [`GET /instruments`](https://docs.godarkdex.com/docs/get-instruments)): | Rate | Default | Meaning | | --- | --- | --- | | Maintenance margin | 500 bps (5%) | Minimum equity as a fraction of notional at mark | | Warning margin | 1,000 bps (10%) | Early warning band (internal classification) | Per-instrument fields `initial_margin_ratio` and `maintenance_margin_ratio` on [`GET /instruments`](https://docs.godarkdex.com/docs/get-instruments) are authoritative for each market. ## Pre-Trade Risk Checks Every order is risk-checked **before** it enters the book. A successful `POST /orders` response means all checks passed — not that the order has filled. | Check | Error code | Description | | --- | --- | --- | | Margin sufficiency | `1410` | Available collateral insufficient for the requested size | | Position limits | `1411` | Position size exceeds instrument cap | | Account in liquidation | `1412` | New orders blocked while a liquidation is in progress | | Leverage above max | `1413` | Requested leverage exceeds instrument `max_leverage` | Resting orders also reserve margin optimistically (order holds) so `free_collateral` reflects working liquidity. See [Place Order — Pre-Trade Risk Validation](https://docs.godarkdex.com/docs/place-order#pre-trade-risk-validation) and [Error Codes](https://docs.godarkdex.com/docs/error-codes). Pre-trade checks **fail closed** on stale or missing oracle prices — orders are rejected rather than accepted without a valid mark. ## Margin Health Tiers The liquidation monitor evaluates every open position approximately every **250 ms**. Each position is classified into one of six tiers based on **margin ratio** (equity ÷ maintenance margin, expressed in basis points where 10,000 = 100%). | Tier | Margin ratio | User-visible action | | --- | --- | --- | | **Healthy** | > 150% | No alert | | **Warning150** | 120% – 150% | Margin alert (web UI banner / health bar) | | **Critical120** | 110% – 120% | Margin alert; same-side resting orders may be cancelled | | **T1** | 100% – 110% | First liquidation tranche — **10%** of original position size; all user orders cancelled | | **T2** | 80% – 100% | Second tranche — **30%** of original size (requires T1 complete) | | **T3** | ≤ 80% | Third tranche — **60%** of original size (requires T2 complete) | The web trading UI mirrors these bands in the margin health bar and tier banners. Tier names here are **margin health tiers**, not [VIP fee tiers](https://docs.godarkdex.com/docs/vip-tiers). ### Partial Liquidation Ladder When a position crosses into T1, T2, or T3, the engine liquidates a **fraction of the original position size** (not the remaining size): | Tranche | Size liquidated | Cumulative | | --- | --- | --- | | T1 | 10% of original | 10% | | T2 | 30% of original | 40% | | T3 | 60% of original | 100% | Between tranches the monitor pauses briefly (2s / 3s / 5s) and re-evaluates. If margin ratio recovers above **130%** (120% + 10% hysteresis), the position returns to normal monitoring without further tranches. If tranches cannot restore solvency — for example, due to timeout, repeated defer failures, or persistent deficit — the engine escalates to **ADL** (auto-deleveraging) against counterparties ranked by profit and leverage. ## Liquidation Process End-to-end flow: 1. **Monitor tick** — sequencer evaluates margin ratios for all open positions 2. **Tier classification** — position enters Warning150 / Critical120 / T1 / T2 / T3 3. **Alerts** — margin alerts pushed to connected clients (web UI and programmatic subscribers) 4. **Order cancellation** — at T1, all resting user orders on the account are cancelled 5. **Tranche execution** — position slice transferred from user to the GoDark Liquidation Vault (GLV) via `transfer_tranche` 6. **Unwind** — GLV inventory is unwound through internal market-making strategies 7. **On-chain settlement** — collateral split settled on Solana via the shielded-pool `liquidate` instruction (see [Settlement](https://docs.godarkdex.com/docs/settlement) and [Shielded Pool](https://docs.godarkdex.com/docs/shielded-pool)) On-chain liquidation settles **collateral** (ZK split from user remainder to GLV credit). Position sizing, tier logic, and tranche scheduling run off-chain in the sequencer. Oracle mark prices (Pyth primary, Switchboard failover) drive PnL and liquidation math. Stale oracle data can delay or block pre-trade checks; the monitor uses the same mark feed for ongoing evaluation. ## Liquidation Price Each open position exposes a `liquidation_price` field — the mark price at which maintenance margin would equal equity (the boundary between Critical120 and T1). Returned by [`GET /positions`](https://docs.godarkdex.com/docs/positions) and the [Positions Channel](https://docs.godarkdex.com/docs/ws-user-events). Recomputed when mark price moves (`update_reason: mark_price`) or when the position changes due to fills or liquidations. Approximate formulas (using maintenance rate `MMR` in basis points, `BPS = 10_000`): ``` Long: liq = (size × entry − collateral) × BPS / (size × (BPS − MMR)) Short: liq = (collateral + size × entry) × BPS / (size × (BPS + MMR)) ``` Higher leverage means less initial collateral for the same size, so liquidation price sits closer to entry. ## Bad Debt Backstop When liquidation and ADL cannot fully cover a deficit (negative equity / bad debt), a three-tier backstop applies: | Tier | Mechanism | | --- | --- | | 1 | **Insurance fund** — absorbs residual loss up to fund balance (funded by a fraction of trading fees; see [Fee Structure](https://docs.godarkdex.com/docs/fee-structure)) | | 2 | **Socialized loss** — if the fund is exhausted, loss may be distributed across profitable positions in the same market | | 3 | **Protocol halt** — if socialized loss exceeds a configurable threshold, the market is halted pending manual intervention | Insurance fund and socialized-loss accounting are tracked off-chain in the current release; on-chain vault integration is planned for a future version. ## Programmatic Integration ### REST | Endpoint | Relevant fields | | --- | --- | | [`GET /positions`](https://docs.godarkdex.com/docs/positions) | `liquidation_price`, `margin`, `leverage`, `unrealized_pnl` | | [`GET /instruments`](https://docs.godarkdex.com/docs/get-instruments) | `initial_margin_ratio`, `maintenance_margin_ratio`, `max_leverage` | | [`POST /orders`](https://docs.godarkdex.com/docs/place-order) | Pre-trade risk rejection codes `1410`–`1413` | ### WebSocket Subscribe to the [Positions Channel](https://docs.godarkdex.com/docs/ws-user-events) for live updates: | `update_reason` | Meaning | | --- | --- | | `mark_price` | Mark moved — PnL and `liquidation_price` recomputed | | `liquidation` | Position partially or fully liquidated | | `fill` | Size or margin changed due to a trade | Margin health tier alerts are delivered to connected web clients. Integrators should monitor `liquidation_price`, position size changes with `update_reason: liquidation`, and risk error codes on order placement. ### Error codes | Code | When | | --- | --- | | `1410` | Margin insufficient | | `1411` | Position limit exceeded | | `1412` | Account in liquidation — new orders blocked | | `1413` | Leverage above instrument max | Full reference: [Error Codes](https://docs.godarkdex.com/docs/error-codes). ## Related - [Trade Flow](https://docs.godarkdex.com/docs/trade-flow) — order lifecycle including MPC margin checks - [MPC Committee Architecture](https://docs.godarkdex.com/docs/mpc-architecture) — where matching and risk evaluation run - [Positions](https://docs.godarkdex.com/docs/positions) — position snapshot API - [Settlement](https://docs.godarkdex.com/docs/settlement) — batch settlement and oracle role - [VIP Tiers](https://docs.godarkdex.com/docs/vip-tiers) — fee tiers (distinct from margin health tiers) ================================================================================ Source: https://docs.godarkdex.com/docs/settlement/ # Settlement All trades matched within GoDark's MPC engine are settled against private collateral commitments in the GoDark shielded pool. ![Settlement Flow](https://docs.godarkdex.com/images/architecture/client-settlement-flow.png) ## Settlement Overview | Aspect | Detail | |--------|--------| | Settlement chain | Solana | | Settlement mechanism | Proof-backed shielded-pool state transitions submitted on-chain | | Signature requirement | **3-of-5 committee members** must co-sign each settlement batch | | Confirmation | Solana slot/block production is typically ~400ms; finalized settlement follows Solana finality. | | Collateral | Deposited into a shielded pool and represented as private note commitments | | Oracle prices | Public price feeds ingested from Solana; used for liquidation and funding rate calculations (see [Margin & Liquidation](https://docs.godarkdex.com/docs/margin-and-liquidation)) | Your funds remain under on-chain program controls at all times. GoDark's MPC committee does not take custody of collateral; it produces matched outcomes that are settled as shielded-pool state transitions. ## Settlement Flow 1. **Wallet creation** — Sign up with your email to receive a [Fireblocks](https://www.fireblocks.com/) embedded wallet. 2. **Deposit and shield** — Deposited USDC is automatically shielded into GoDark's private collateral pool. 3. **Trading** — Trades execute off-chain in the MPC matching engine. Matched outcomes are converted into private settlement updates. 4. **Committee approval** — Settlement batches require 3-of-5 committee member authorization before on-chain submission. 5. **Shielded settlement** — On-chain settlement consumes private input notes and creates new private output commitments. No per-user balance ledger is published. 6. **Ghost withdrawal** — Withdrawing proves ownership of a private commitment and releases collateral to a fresh ephemeral recipient address designed to reduce public linkability back to the user's wallet. ## Shielded Pool Model | Property | Description | |----------|-------------| | **Custody** | SPL tokens are held in aggregate program-controlled vault accounts. | | **Private accounting** | User collateral is represented as private note commitments rather than readable per-user vault balances. | | **Solvency** | Aggregate vault balances can be compared against the sum of unspent private notes for each mint. | | **Auditability** | Public events expose enough structure to monitor activity and solvency without revealing user-level trade data. | For the full model, see [Shielded Pool](https://docs.godarkdex.com/docs/shielded-pool). ## Settlement Query Endpoints | Endpoint | Description | |----------|-------------| | `GET /settlement/status/:batch_id` | Get batch status. Returns: `{ batch_id, status, tx_signature, trade_count, created_at }` | | `GET /settlement/stats` | Get settlement stats. Returns: `{ total_settled, success_rate, pending_batches, failed_batches }` | ## Batch Settlement Mechanics - **Batching window:** Configurable (1–2 seconds default) - **Committee authorization:** Each batch requires 3-of-5 MPC committee members to approve before on-chain submission. - **Private state update:** Settlement consumes private input notes and creates private output commitments. - **Proof-backed execution:** On-chain verification checks ownership, conservation, and operation validity before state changes commit. - **No per-fill SPL movement:** SPL moves at deposit and ghost-withdrawal boundaries; matched trades update shielded-pool state. ## Settlement Finality - Settlement transactions are submitted to Solana and confirmed on-chain. - Once the settlement transaction reaches Solana finality, settlement is irreversible. - Aggregate pool activity is auditable via the Solana ledger while per-user amounts, positions, and counterparties remain private. ================================================================================ Source: https://docs.godarkdex.com/docs/fee-structure/ # Fee Structure GoDark uses a maker-taker model with rebates for top tiers. Fees are tier-driven — for a user's authoritative rates, hit [`GET /account/vip`](https://docs.godarkdex.com/docs/vip-tiers). ## Tier Summary | Attribute | Core | Select | Advanced | Prime | Apex | | --- | --- | --- | --- | --- | --- | | 30D Notional Volume | $0 | $5M | $10M | $25M | $50M | | Maker Fee | 0.02% | 0.01% | 0.00% | -0.005% | -0.01% | | Taker Fee | 0.05% | 0.04% | 0.03% | 0.025% | 0.02% | | Min Notional | $25 | $50 | $75 | $90 | $100 | | Instant Taker Bonus | 5% | 7.5% | 10% | 12.5% | 20% | | Hourly Taker Bonus | 5% | 10% | 12.5% | 15% | 25% | Negative maker fees are rebates credited to the maker. **Instant Taker Bonus** — a percentage of taker fees rebated to the maker at trade execution. **Hourly Taker Bonus** — an additional percentage of taker fees distributed hourly to makers, proportional to liquidity provided during the window. ## Where to read fee values | Data | Where to read it | | --- | --- | | Full tier schedule (public) | [`GET /vip/tiers`](https://docs.godarkdex.com/docs/vip-tiers) | | **Your** current fees | [`GET /account/vip`](https://docs.godarkdex.com/docs/vip-tiers) | | Instrument-default fees | [`GET /instruments`](https://docs.godarkdex.com/docs/get-instruments) (tier-0 defaults only) | When these disagree, `GET /account/vip` is authoritative for execution and settlement. ## Fee Collection - Maker and taker fees are computed at match time and included in the net position delta. - Fees are deducted at settlement. - Fees are transferred in USDC to the GoDark fee wallet as part of the settlement transaction. See [VIP Tiers](https://docs.godarkdex.com/docs/vip-tiers) for how tier progression and rolling 30d volume are computed. --- ================================================================================ Source: https://docs.godarkdex.com/docs/mpc-architecture/ # MPC Committee Architecture GoDark uses Secure Multi-Party Computation (MPC) with a 5-party committee to provide cryptographic order privacy while maintaining sub-millisecond matching latency. ## How MPC Protects Your Orders When you submit an order to GoDark, it is never sent as plaintext to any single server. Instead: 1. **Secret sharing** — Your order is split into 5 cryptographic shares using Shamir Secret Sharing 2. **Distributed computation** — Each share is sent to a different, independently operated node 3. **Encrypted matching** — The 5 nodes compute on these shares directly — matching orders, checking prices, updating positions — without ever reconstructing the original data 4. **Threshold output** — Results are only revealed when the protocol's output step combines at least 3 shares Any single share — or even any two shares — is mathematically indistinguishable from random noise. ![Shamir Secret Sharing](https://docs.godarkdex.com/images/architecture/client-shamir-secret-sharing.png) ## The 5-Party Committee ![5-Party Committee & Operator Pool](https://docs.godarkdex.com/images/architecture/client-committee-operator-pool.png) | Property | Detail | |----------|--------| | Active committee size | 5 nodes | | Threshold | 3-of-5 (any 3 nodes can complete a computation) | | Operator pool | Large pool of vetted, bonded node operators | | Operator independence | Different organizations, different countries, different legal jurisdictions | | Fault tolerance | Any 2 nodes can crash or go offline without interrupting matching | ### Why 5 Parties? | Benefit | Explanation | |---------|-------------| | **Collusion resistance** | An attacker must compromise 3 independent operators (across jurisdictions) to see any order | | **Fault tolerance** | 2 nodes can fail simultaneously with zero downtime — superior to single-sequencer architectures | | **Performance** | 5-party Shamir with preprocessing achieves sub-millisecond latency per order | | **Practical threshold** | 3-of-5 balances security (majority required) with liveness (only 3 needed to operate) | ## What This Means for You - **Your order is private from operators** — Each node operator sees only a random-looking share of your order. They cannot determine your price, size, direction, or identity. - **Collusion-resistant** — Reconstructing any order requires at least 3 of the 5 node operators to collude. The operators are independent organizations in different legal jurisdictions, and the committee membership rotates continuously. - **Cryptographic guarantee, not a policy promise** — Privacy is enforced by mathematics, not by terms of service or hardware assumptions. ## Offline / Online Computation Model GoDark uses a preprocessing model to achieve low-latency matching: ![Offline/Online Phases](https://docs.godarkdex.com/images/architecture/client-offline-online-phases.png) | Phase | What Happens | When | |-------|--------------|------| | **Offline (preprocessing)** | Nodes collaboratively generate cryptographic material in the background. This is computationally expensive but runs continuously ahead of time. | Always running in background | | **Online (matching)** | When your order arrives, the matching engine consumes pre-generated material to execute comparisons and fills. Each operation requires only lightweight share arithmetic and a small number of communication rounds. | At order submission time | This split is what allows GoDark to match orders in sub-millisecond latency despite running a full MPC protocol. ## What Runs Inside MPC (And What Doesn't) Not everything needs to be private. GoDark places only the privacy-sensitive operations inside the MPC boundary: ![MPC Boundary](https://docs.godarkdex.com/images/architecture/client-mpc-boundary.png) | Inside MPC (Private) | Outside MPC (Public) | |----------------------|----------------------| | Order content (price, size, direction) | Authentication | | Order matching | Rate limiting | | Position calculations | Input validation | | Margin/risk checks | Settlement to Solana (see [Margin & Liquidation](https://docs.godarkdex.com/docs/margin-and-liquidation)) | ## Rolling Rotation & Warm Standby GoDark's MPC nodes are co-located (in the same datacenter) for sub-millisecond latency. To prevent this co-location from becoming a single point of failure, GoDark employs rolling rotation with warm standby across geographically distributed datacenter clusters. ### Within-Cluster Rotation ![Within-Cluster Rotation](https://docs.godarkdex.com/images/architecture/client-within-cluster-rotation.png) | Property | Detail | |----------|--------| | Scope | 1 node replaced per rotation epoch | | Matching downtime | Zero — share refresh (Proactive Secret Sharing) happens while matching continues | | Effect | Breaks any forming collusion; continuously changes which operators hold active shares | After a full rotation cycle, every committee seat has been held by a different operator than when the cycle started. ### Cross-Cluster Migration Periodically, the entire active committee migrates to a different datacenter cluster in a different geographic region: ![Cross-Cluster Migration](https://docs.godarkdex.com/images/architecture/client-cross-cluster-migration.png) | Property | Detail | |----------|--------| | Scope | All 5 active nodes transition to a new cluster | | Matching downtime | Milliseconds (with warm standby) | | Effect | System is never in one jurisdiction long enough to be a static target | ### Warm Standby To minimize disruption during cross-cluster migration, GoDark uses warm standby clusters that continuously shadow the active cluster's state. At switchover time, only a small delta needs to transfer — resulting in near-zero matching gaps that are imperceptible to traders. ## Collusion Resistance ![Collusion Resistance](https://docs.godarkdex.com/images/architecture/client-collusion-resistance.png) | Scenario | Difficulty | |----------|------------| | 1 operator compromised | No impact — 1 share reveals nothing | | 2 operators colluding | No impact — 2 shares reveal nothing (3-of-5 threshold) | | 3 operators colluding | Theoretically possible — but operators are from different jurisdictions and rotate continuously | | All 5 operators colluding | Would break privacy — requires coordinated compromise of 5 independent organizations across multiple jurisdictions with continuous rotation | ## Fault Tolerance ![Fault Tolerance](https://docs.godarkdex.com/images/architecture/client-fault-tolerance.png) | Failure Scenario | Impact | Recovery | |------------------|--------|----------| | 1 node crashes | None — matching continues with 4 of 5 nodes | Crashed node rejoins and re-syncs | | 2 nodes crash simultaneously | None — matching continues with 3 of 5 nodes (threshold met) | Nodes rejoin and re-sync | | 3 nodes crash simultaneously | Brief pause — warm standby cluster takes over | Automatic failover in ~20–50ms | | Active datacenter goes offline | ~20–50ms blip — warm standby cluster takes over | Automatic failover; no manual intervention | | Network partition between nodes | Nodes on the majority side continue; minority side pauses | Automatic healing when partition resolves | This is a meaningful improvement over single-sequencer architectures, where any failure of the sequencer halts the entire exchange. ================================================================================ Source: https://docs.godarkdex.com/docs/privacy-encryption/ # Privacy & Encryption GoDark is a perpetual futures exchange where **no single party — not even the operators running the system — can see your orders, positions, or trading strategy**. Traditional exchanges (centralized or decentralized) expose order data to operators, sequencers, or validators. This creates a fundamental conflict of interest: the entity running the matching engine can front-run, sandwich, or selectively delay orders. GoDark significantly reduces this exposure using **Secure Multi-Party Computation (MPC)** and dark-pool execution. ## The Problem: Who Can See Your Orders? | Exchange Type | Who sees your orders | Risk | |---|---|---| | **Centralized (Binance, Bybit)** | The exchange operator | Operator can front-run, trade against you, or leak data | | **On-chain DEX (dYdX, Hyperliquid)** | The sequencer / validator | Sequencer can reorder or censor transactions (MEV) | | **GoDark** | **No single party** — order data is cryptographically split across 5 independent nodes | No single party (or any pair of colluding parties) can reconstruct your order | ## How MPC Protects Your Orders When you submit an order to GoDark, it is never sent as plaintext to any single server. Instead, your order is split into **5 cryptographic shares** using a technique called **Shamir Secret Sharing**. Each share is sent to a different, independently operated node. Any single share — or even any two shares — is mathematically indistinguishable from random noise. The 5 nodes then **compute on these shares directly** — matching orders, checking prices, updating positions — without ever reconstructing the original data. The matching engine operates on encrypted fragments, producing results that are only revealed when the protocol's output step combines the necessary shares. ### What This Means for You - **Your order is private from operators** — Each node operator sees only a random-looking share of your order. They cannot determine your price, size, direction, or identity. - **Collusion-resistant** — Reconstructing any order requires at least 3 of the 5 node operators to collude. The operators are independent organizations in different legal jurisdictions, and the committee membership rotates continuously. - **Cryptographic guarantee, not a policy promise** — Privacy is enforced by mathematics, not by terms of service or hardware assumptions. The result: traders interact with familiar REST and WebSocket APIs. The MPC layer is transparent — you submit orders the same way you would on any exchange. The privacy happens at the infrastructure level. For details on the committee structure, rotation model, and fault tolerance, see [MPC Committee Architecture](https://docs.godarkdex.com/docs/mpc-architecture). ## Order Lifecycle ### Submitting an Order 1. You submit an order to the nearest **Edge Gateway** over a TLS-encrypted connection. 2. The Edge Gateway handles authentication, rate limiting, and input validation. Order payloads are encrypted in transit before MPC fanout (see [Encryption & Transport](https://docs.godarkdex.com/docs/encryption) for gateway trust boundaries). 3. The **Sequencer Gateway** assigns a global sequence number, ensuring deterministic ordering, and fans the order to all 5 MPC nodes simultaneously. 4. The MPC committee secret-shares your order, matches it against the secret-shared orderbook, updates positions, and runs margin checks — all without any single node seeing the data. 5. You receive an acknowledgment once 3 of 5 nodes confirm the operation. 6. Filled trades are batched and settled to Solana periodically. ### Two-Tier Gateway Architecture | | Edge Gateways | Sequencer Gateway | |---|---|---| | **Location** | Deployed near traders (multiple regions) | Co-located with MPC nodes | | **Scaling** | Horizontal — scales to handle any number of connections | Single instance with hot standby | | **Role** | TLS termination, authentication, rate limiting, WebSocket management | Sequence number assignment, parallel fanout to 5 nodes | | **Order privacy at gateway** | Encrypted session framing before MPC fanout | Sequence assignment only; no MPC plaintext | Gateway encryption protects order contents from passive observers and from logs/traces. A compromised gateway is a separate trust boundary — see [Encryption & Transport](https://docs.godarkdex.com/docs/encryption). This means a trader in Tokyo connects to a local Edge Gateway with ~2ms TLS handshake (instead of 300ms to a distant datacenter), while the Sequencer Gateway focuses purely on ordering and distribution. ## Settlement All trades matched within GoDark's MPC engine settle against private commitments in the shielded pool. Collateral remains under on-chain program controls, and GoDark's MPC committee cannot arbitrarily move user funds. For full details, see [Settlement](https://docs.godarkdex.com/docs/settlement). ## Summary | Dimension | GoDark Guarantee | |---|---| | **Order privacy** | Cryptographic — no single operator (or any two colluding operators) can see your orders | | **Matching latency** | Sub-millisecond (~150–750μs per order) | | **Throughput** | 10,000+ orders/second | | **Fault tolerance** | Any 2 of 5 nodes can fail without downtime | | **Geographic resilience** | Automatic failover across multiple global regions | | **Collusion resistance** | 3-of-5 threshold with rolling rotation across independent operators in different jurisdictions | | **Settlement** | On-chain (Solana) through program-controlled shielded-pool commitments | GoDark delivers the performance traders expect from a centralized exchange, the programmatic custody controls and transparency of a decentralized exchange, and a level of order privacy that neither can offer. Collateral privacy is handled by a separate shielded-pool layer. Deposits become private note commitments, and settlement updates those commitments without publishing a readable per-user balance ledger. See [Shielded Pool](https://docs.godarkdex.com/docs/shielded-pool) for the custody and settlement privacy model. ================================================================================ Source: https://docs.godarkdex.com/docs/shielded-pool/ # Shielded Pool The GoDark shielded pool is the collateral privacy layer for the exchange. It lets users deposit USDC, trade against private collateral commitments, and withdraw through ephemeral recipient addresses without publishing a readable per-user balance or trade history on-chain. The design gives evaluators two things to inspect: - **Public token custody** — real SPL tokens live on Solana in aggregate vault accounts controlled by program-derived authorities. - **Private accounting** — user balances and trade state are represented as shielded notes in a compressed commitment tree. ## What It Provides The shielded pool is designed around four goals: | Goal | What it means | |---|---| | **Collateral privacy** | Deposits become private note commitments before trading. Public observers do not see a per-user balance ledger. | | **Private settlement** | Trades update private notes rather than publishing readable price, size, direction, or counterparty data. | | **Programmatic custody controls** | Token movement is gated by Solana programs, proof checks, and program-derived authorities rather than operator discretion. | | **Evaluator visibility** | Public events and aggregate balances allow third parties to monitor solvency and activity without seeing user-level trading data. | ## Mental Model: Public Tokens, Private Notes There are two ledgers: 1. **Public Solana ledger** — SPL token balances. Public movement happens when funds enter the pool or leave it. 2. **Private note ledger** — opaque commitments and nullifiers. Trading, transfers, and settlement mutate this private state without moving SPL tokens for every match. When a user deposits USDC into their Dynamic wallet, GoDark automatically shields the collateral for trading. The visible deposit is converted into a private note commitment inside the shielded pool. From that point forward, the trading layer works with commitments, not a readable per-user balance account. ## Technologies Used The shielded-pool stack uses standard privacy and Solana primitives where possible, with custom circuits only where the exchange-specific settlement logic requires them. | Layer | Technology | How GoDark uses it | |---|---|---| | **Base chain** | Solana | Final settlement, SPL token custody, public transaction ordering, and program execution. | | **Token custody** | SPL Token accounts + Program Derived Addresses (PDAs) | Deposited collateral is held in aggregate program-controlled vault accounts rather than operator wallets. | | **Compressed private state** | Light Protocol | Stores shielded note leaves and enforces commitment/nullifier uniqueness in compressed state. | | **Note commitments** | Poseidon commitments | Represents private collateral notes using hash commitments over note fields such as asset, amount, owner key, and randomness. | | **Nullifiers** | Poseidon nullifiers | Marks a private note as spent without revealing the original commitment owner or note contents. | | **ZK proving system** | Groth16 over the BN254 scalar field | Verifies shield, transfer, settlement, and ghost-withdrawal transitions with compact on-chain proofs. | | **Circuit families** | Shield, transfer, match, and withdraw circuits | Enforce ownership, conservation of value, valid note spends, and valid output creation for each operation type. | | **Private matching** | MPC committee using Shamir-style secret sharing | Matches encrypted order flow without any single node seeing the complete orderbook or user order. | | **Batch authorization** | Threshold signing | Requires committee quorum approval before settlement batches are submitted on-chain. | | **Withdrawal privacy** | Ephemeral recipient addresses | Ghost withdrawals release funds to fresh recipient addresses designed to reduce public linkability to the user's Dynamic wallet. | The docs intentionally describe these technologies at the integration and invariant level. Circuit source, verifier-key operations, deployment keys, and exploit-specific audit details are not published in public docs. ## Fund Flow | Phase | Public token movement | Private state change | |---|---|---| | **Deposit** | USDC enters the pooled vault from the user's wallet flow. | A one-time deposit authorization is created. | | **Shield** | No additional token movement. | A private note commitment is added to the commitment tree. | | **Trade or transfer** | No SPL movement. | Existing notes are nullified and new commitments are created. | | **Withdraw** | USDC leaves the pooled vault to an ephemeral recipient address. | A private note is consumed by publishing its nullifier. | This separation is the core privacy property: tokens move publicly at the edges, while the middle of the lifecycle is private-ledger arithmetic. ## What Observers Can and Cannot See | Operation | Publicly observable | Hidden from observers | |---|---|---| | **Deposit** | A token deposit occurred into the pool flow. | The future commitment that deposit becomes after shielding. | | **Shield** | An opaque commitment was appended. | Owner, amount, and note randomness. | | **Trade / transfer** | Nullifiers and new commitments were emitted. | Trade size, price, direction, ownership, and counterparty mapping. | | **Ghost withdraw** | A fresh recipient address receives tokens from the pool. | The user's identity, prior note history, trading path, and source commitment. | The pool does not claim that public token movements disappear. Deposits and withdrawals still settle on Solana. The privacy guarantee is unlinkability: by default, withdrawals use fresh ephemeral recipient addresses so observers can see that funds left the aggregate pool, but should not be able to trace that output back to the user's Dynamic wallet, prior note history, trading path, or counterparties. ## Conservation and Solvency For each supported mint, the pool is built around a simple solvency invariant: > Aggregate SPL in the pooled vault equals the sum of all unspent private notes for that mint. The system enforces this through layered checks: - **No shield without deposit** — a deposit authorization can be consumed only once. - **No double-spend** — spending a note publishes a nullifier; the same nullifier cannot be inserted twice. - **No duplicate output note** — output commitments must be unique in the compressed state layer. - **No wrong-recipient release** — withdrawals bind the released tokens to the ephemeral recipient proven by the withdrawal flow. - **No trade-side token movement** — matching changes private note state; it does not move SPL tokens per fill. Third-party evaluators can reason about the public aggregate vault balance, emitted commitment/nullifier events, and the private-note accounting model without needing access to user-level trading data. ## Security Controls The shielded pool uses defence in depth rather than relying on a single control: | Layer | Purpose | |---|---| | **Proof verification** | State transitions require proof-backed ownership, arithmetic, and conservation checks. | | **Commitment and nullifier uniqueness** | The compressed state layer prevents duplicate commitments and repeated spends. | | **Program-bound custody** | Vault release paths are bound to the shielded-pool program and PDA-signed authorities. | | **Circuit and version binding** | Proofs are scoped to a specific operation type and protocol version. | | **Operational kill switches** | Deposits, withdrawals, transfers, matching, and sponsored withdrawals can be paused independently. | | **Monitoring and event hygiene** | Public events are minimized, and monitoring tracks pool health, activity, and anonymity-set conditions. | These controls are deliberately independent. A failure in one layer should not silently bypass custody, proof validity, uniqueness, and operational response controls at the same time. ## Audit and Operational Posture GoDark has run an internal shielded-pool security review covering proof flow, custody boundaries, event privacy, operational controls, and off-chain logging. The highest-risk remediation work has been prioritized around fund safety, privacy leakage, and production-deployment guardrails. Public-facing posture: - Security-sensitive controls are staged through testnet validation before production rollout. - Operational authorities are designed to move toward multisig and timelocked governance. - Public events are intentionally minimal so indexers can monitor pool state without reconstructing user graphs. - Future cryptographic upgrades are planned as coordinated migrations rather than piecemeal changes that could split verifier, circuit, and state assumptions. ## Disclosure Boundary This page intentionally describes the model, invariants, and trust boundaries without publishing every internal implementation detail. GoDark does not expose full exploit narratives, deployment keys, verifier-key operational procedures, or low-level circuit internals in public docs. For adjacent context, see [Deposit Funds](https://docs.godarkdex.com/docs/deposit-funds), [Settlement](https://docs.godarkdex.com/docs/settlement), [Privacy & Encryption](https://docs.godarkdex.com/docs/privacy-encryption), and [MPC Committee Architecture](https://docs.godarkdex.com/docs/mpc-architecture).