Skip to content

Spec drift: gemini-titan — CRITICAL order schema breaking changes: status enum changed to uppercase, side changed to uppercase, type renamed to orderType #2001

Description

@realfishsam

Exchange

gemini-titan

Drift Type

changed_response / changed_params

Severity

HIGH — order status matching in normalizer will never match live values; order submission may send wrong side value

Their Docs

Source: https://developer.gemini.com/prediction-markets-spec (changelog entries from 2026)

Order status enum completely changed (POST /v1/prediction-markets/order response):

Old value (our spec) New value (live API)
pending NEW
(new) OPEN
filled FILLED
(new) PARTIALLY_FILLED
cancelled CANCELED
rejected (removed)

Order side values changed (POST /v1/prediction-markets/order — both request and response):

  • buyBUY
  • sellSELL

Field renames in order request/response:

  • Request: typeorderType (live docs use orderType; market order type also removed — only limit and stop-limit supported)
  • Response: avgPriceavgExecutionPrice

New required-in-practice order request fields (not in spec):

  • eventOutcome: "YES" | "NO" — required to specify which leg to trade
  • timeInForce: GTC | FOK | IOC | maker-or-cancel

Our Cached Spec

core/specs/gemini-titan/GeminiTitan.yaml — operationId submitOrder (POST /v1/prediction-markets/order) documents:

  • status enum: ["pending", "filled", "cancelled", "rejected"] (lowercase)
  • side: "buy" / "sell" (lowercase)
  • Request field: type (not orderType)
  • No eventOutcome or timeInForce fields

callApi() References at Risk

None — the gemini-titan adapter does not use callApi(). All HTTP calls are hardcoded:

  • POST ${baseUrl}/v1/prediction-markets/order at fetcher.ts:209 (submit order)
  • POST ${baseUrl}/v1/prediction-markets/order/cancel at fetcher.ts:217 (cancel)
  • POST ${baseUrl}/v1/prediction-markets/orders/active at fetcher.ts:223 (active orders)
  • POST ${baseUrl}/v1/prediction-markets/orders/history at fetcher.ts:227 (order history)

Hardcoded URL Bypasses

fetcher.ts:209 posts the order body constructed in index.ts. If index.ts builds { type, side, ... } with lowercase values, the live API will reject the order or misinterpret it.

normalizer.ts:314 reads raw.status to populate normalized order status. If the mapping compares against lowercase values ('filled', 'pending', etc.), every live order will have an incorrect status (since live returns FILLED, NEW, OPEN, CANCELED).

normalizer.ts:311 reads raw.side — if side is now BUY/SELL, any comparison against 'buy'/'sell' strings in the normalizer or downstream code will fail.

Impact

  • Order submission: may fail or be rejected if type field is sent instead of orderType, or if side is lowercase
  • Status tracking: all order statuses in normalized output will be wrong or unrecognized — FILLED orders will appear as unknown status; PARTIALLY_FILLED is a new state the adapter cannot handle
  • avgExecutionPrice: normalizer.ts:325 may read raw.avgPrice which no longer exists; average execution price will be undefined for all orders

Found by automated spec drift audit

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions