> ## Documentation Index
> Fetch the complete documentation index at: https://docs.testnet.dev.adipredictstreet.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Platform overview

> How PredictStreet splits responsibility between off-chain services for speed and on-chain contracts for custody.

PredictStreet is built around a deliberate split: the **hot path is
off-chain** for sub-second trading latency, and **custody and settlement
are on-chain** so nothing moves without a user's EIP-712 signature
against a dedicated vault contract they control.

## System diagram

```mermaid theme={null}
flowchart LR
    subgraph Client
        W[Wallet]
    end

    subgraph Off-chain
        CA[core-api<br/>X-Api-Key · REST]
        EX[exchange-service<br/>balances · orders]
        MC[matching-core<br/>in-memory orderbook]
        OR[oracle-service<br/>consensus resolver]
        MS[match-submitter<br/>on-chain tx broadcaster]
        CW[chain-watcher<br/>event indexer]
        WS[ws-gateway<br/>real-time]
    end

    subgraph On-chain
        V[User Vault<br/>EIP-1167 clone]
        CT[ConditionalTokens]
        CX[CTFExchange]
        NRA[NegRiskAdapter]
        PSO[PredictStreetOracle]
    end

    W -- HTTPS --> CA
    W -- WSS --> WS
    CA -- HTTP --> EX
    EX -- gRPC --> MC
    EX -- read-only SQL --> CA
    OR -- NATS --> EX
    OR -- tx --> PSO
    MS -- batched tx --> CX
    MS -- batched tx --> NRA
    EX -- trades table --> MS
    CW -- NATS events --> EX
    CW -- NATS events --> OR
    W -- sign only --> V
    V --> CT
    V --> CX
    V --> NRA
```

## Off-chain services

<AccordionGroup>
  <Accordion title="core-api" defaultOpen>
    Client-facing HTTP gateway. Partner traffic authenticates with
    `X-Api-Key` on `core.api.dev.predictstreet.sde.adifoundation.ai`; retail user sessions
    (SIWE) live on a separate surface, `app.predictstreet.io`, and
    are out of scope for this documentation. Rate limits, geo and
    compliance guards, KYC gating. Every request enters here before
    being routed to the appropriate back-end. Owns compliance
    screening (Global Ledger), sanctions, banned-wallet checks, and
    cleared deposit-sources enforcement. See
    [Authentication overview](/auth/overview) and
    [API keys](/auth/api-keys).
  </Accordion>

  <Accordion title="exchange-service">
    Orders, balances, trades, fees, withdrawals. PostgreSQL-backed
    single source of truth for off-chain state. Verifies EIP-712
    signatures, locks balance, calls matching-core over gRPC, persists
    results, publishes events to NATS JetStream.
  </Accordion>

  <Accordion title="matching-core">
    In-memory central-limit orderbook engine (Go). One engine per
    market. Implements FIFO priority within a price level; supports
    GTC / IOC / FOK time-in-force and LIMIT / MARKET order types.
    Stateless from a client perspective — exchange-service holds
    authoritative PG state; matcher state is warm-restartable.
  </Accordion>

  <Accordion title="oracle-service">
    Polls three independent sports data providers
    (Stats Perform primary + API-Football + Sportmonks), evaluates
    consensus (3-of-3 auto-proposes; 2-of-3 blocks unless the
    discrepancy is explainable against the primary source), and
    posts outcomes on-chain via `PredictStreetOracle.proposeOutcome`.
    Handles the 2-hour challenge window, override, void, and
    delayed-data paths. See
    [Settlement overview](/concepts/settlement/overview).
  </Accordion>

  <Accordion title="match-submitter">
    Broadcasts matched trades on-chain in batches. Maintains a pool
    of pre-funded **operator EOAs** (whitelisted via
    `CTFExchange.addOperator()` on both binary and neg-risk exchanges),
    an atomic per-wallet nonce manager, and a tx-tracker that polls
    receipts and reclassifies stuck or dropped transactions. A
    gas-refiller cron tops up operator wallets from a treasury
    address. On a full revert, trades are marked
    `settlement_failed`; per-order failures come in via
    `MatchFailed` events from chain-watcher.
  </Accordion>

  <Accordion title="ws-gateway">
    WebSocket fan-out. Consumes NATS JetStream events from
    exchange-service and oracle-service and multiplexes channels.
    Handshake auth accepts both `X-Api-Key` (partners) and Bearer JWT
    (retail SIWE) on `/ws/user` AND `/ws/market` — same two schemes
    as HTTP, same scope rules. Neither gateway is open: a handshake
    without a key or token closes `1008 unauthorized`. See
    [WebSocket overview](/concepts/websocket/overview).
  </Accordion>

  <Accordion title="chain-watcher">
    Ponder-based indexer for every PredictStreet contract (Exchange,
    ConditionalTokens, NegRiskAdapter, VaultFactory, Oracle).
    Persists events in durable outbox tables and publishes them to
    NATS JetStream (`chain.>` subjects) with at-least-once delivery.
    Handles seq-gap recovery and reorg rewind. Internal — partners
    consume confirmed state through core-api / WebSocket, not
    directly from chain-watcher.
  </Accordion>
</AccordionGroup>

## On-chain contracts

<AccordionGroup>
  <Accordion title="User Vault (EIP-1167 clone)" defaultOpen>
    One minimal-proxy clone per user, deployed through `VaultFactory`
    on first deposit. Holds the user's ERC-20 collateral (USDC) and
    ERC-1155 outcome positions. Non-upgradeable — the implementation
    is pinned and never swapped under existing vaults.

    **Custody model:** withdrawals, split / merge, and neg-risk
    `convertPositions` require a dual EIP-712 signature (vault owner

    * factory owner). The backend cannot move user funds unilaterally.
      An emergency-withdraw path gives the owner unilateral access with
      a 7-day on-chain timelock.
  </Accordion>

  <Accordion title="CTFExchange">
    Matches and settles signed orders. Implements the PS-QUADRATIC-V1
    taker-fee curve `fee = k × P × (1−P)` per
    [Fees](/concepts/trading/fees). Admin-gated for
    pause / unpause / registerToken / setVaultFactory; operator-gated
    for fillOrder / matchOrders.
  </Accordion>

  <Accordion title="ConditionalTokens">
    Polymarket-compatible ERC-1155 position tokens. `prepareCondition`
    registers a new market condition; position IDs are deterministic
    from `(collateral, conditionId, indexSet)`. Oracle-service calls
    `prepareCondition` as part of market deployment.
  </Accordion>

  <Accordion title="NegRiskAdapter + PredictStreetNegRiskCtfExchange">
    Separate deployment path for multi-outcome categorical markets
    (e.g. 3+ exclusive outcomes). Reuses the same EIP-712 order shape
    as the binary exchange; differences are in the position-token
    derivation and `convertPositions` for NO-basket → collateral
    conversions.
  </Accordion>

  <Accordion title="PredictStreetOracle">
    Single on-chain oracle contract. Oracle-service is its only
    authorized writer for `proposeOutcome` / `finalizeOutcome` /
    `resolveChallenge*` / `voidMarket` / `markDelayed`. Enforces a
    10 USDC challenger bond and a 2-hour challenge window; emergency
    proposal clear is gated by a 7-day admin timelock. See
    [Settlement flow](/concepts/settlement/flow).
  </Accordion>
</AccordionGroup>

## The hot path in one paragraph

A partner calls `POST /api/orders/place` with an EIP-712-signed order. core-api
verifies the `X-Api-Key` header, runs compliance guards, and forwards to
exchange-service. exchange-service verifies the EIP-712 signature
against the expected signer EOA (matching the vault owner for
`SignatureType.VAULT`), locks the required quote notional
(`available → locked`), persists the order row, and calls matching-core
over gRPC. matching-core runs the book, returns fills synchronously.
exchange-service writes the trade rows + fee ledger in a single PG
transaction, publishes events to NATS, and returns the response.
**No on-chain transaction happens here.** Trades are picked up from
the `trades` table by match-submitter, which batches them into
`fillOrder` / `matchOrders` calls against CTFExchange (or the
neg-risk exchange), signed by an operator EOA from its wallet pool.
chain-watcher sees the resulting `OrderFilled` / `MatchFailed`
events and notifies exchange-service to finalize the trade state.

## Strict vs optimistic settlement

PredictStreet uses a **strict settlement** model: a trade row is
persisted immediately after match, but the user's balance is only
decremented from `locked` **after** on-chain confirmation from
chain-watcher. The upside is simpler revert semantics (a reverted chain
tx simply refunds `locked → available`) and no need for an `unsettled`
balance bucket. The tradeoff is a small settlement delay between
match and the balance update being visible as "available" again.

## What partners own vs what PredictStreet owns

| Concern                               | Who owns it                                             |
| ------------------------------------- | ------------------------------------------------------- |
| User custody of USDC + outcome tokens | **User (via their vault)**                              |
| EIP-712 key                           | **User (or their delegated signer)**                    |
| API-key issuance + session lifecycle  | PredictStreet (core-api)                                |
| Balance bookkeeping off-chain         | PredictStreet (exchange-service)                        |
| Orderbook state (hot)                 | PredictStreet (matching-core, in-memory)                |
| Final settlement ledger               | **On-chain — ConditionalTokens / CTFExchange / Vault**  |
| Oracle resolution proposal            | PredictStreet (oracle-service)                          |
| Oracle challenge (dispute)            | **User** (via on-chain bond)                            |
| Fee configuration                     | PredictStreet (admin-api — changes require audit trail) |

The rule of thumb: **anything that moves money is on-chain with a user
signature**. Everything else is off-chain for speed.

## Next

<CardGroup cols={2}>
  <Card title="Authentication" icon="key" href="/auth/api-keys">
    `X-Api-Key` format, scope taxonomy, and rotation.
  </Card>

  <Card title="Order lifecycle" icon="timeline" href="/concepts/trading/order-lifecycle">
    State machine and transition rules.
  </Card>

  <Card title="Contracts reference" icon="file-contract" href="/concepts/contracts/overview">
    Deployed addresses, ABIs, invariants.
  </Card>

  <Card title="Environments" icon="server" href="/environments">
    Testnet, staging, mainnet endpoints.
  </Card>
</CardGroup>
