Skip to content

Data and client state

The network records financial truth in a form optimized for agreement and verification. Trading applications need another form: searchable histories, portfolio views, charts, and live updates.

Indexers create those views from committed blocks. They can be rebuilt from the network record and never become an independent authority over a balance or position.

Each block produces ordered, versioned events. The indexer applies one complete block at a time and derives account balances, positions, open orders, fills, receipts, and market history.

A block is either applied in full or not applied. If validation fails, the previous projection remains available while the service investigates or restarts from an agreed state.

REST endpoints serve current snapshots and historical queries. WebSocket streams begin with a snapshot, then deliver committed updates in cursor order.

The reference indexer checks that block heights are continuous, the chain identity is correct, event versions are supported, cursors are in canonical order, and financial fields use valid values. It rejects duplicate fills and conflicting replays at a height it has already processed.

Balances, positions, orders, receipts, and fills have a canonical sort order. A snapshot restored from archive and an indexer rebuilt from genesis must reach the same projection hash at the same height.

Go, TypeScript, and Python clients consume the same versioned envelope. A client records both the financial values it displays and the block height and cursor that produced them.

This context matters after a disconnect. The client can request the missing event range or replace its local view with a fresh snapshot. It never has to combine new market data with an account balance from an unknown earlier state.

If a WebSocket update is missed, the client stops applying later deltas until it has filled the gap. If the indexer is unavailable, the application can query a healthy node directly for authoritative state.

When local and network values conflict, the committed network result wins. The application discards or rebuilds the conflicting projection and should make the reconciliation visible when it affects the user.

A slow WebSocket subscriber is disconnected instead of delaying ingestion for everyone else. It reconnects from a fresh snapshot or an agreed cursor.

A lost connection does not establish whether a transaction failed. The client queries the durable request receipt before deciding what to do next.

An identical retry returns the original result. A retry that changes the payload while keeping the request ID is rejected, protecting the account from an accidental duplicate action.

The Novrinex exchange follows the same client model as any other application. It can construct transactions, sponsor fees, present account state, and send notifications. It cannot override a committed order, fill, balance, position, or withdrawal.