Skip to content

API contract 2026-10-01: version header, error codes, hasMore, capabilities - #23

Merged
0xFantomMenace merged 4 commits into
masterfrom
feat/api-contract-2026-10
Oct 5, 2026
Merged

0xFantomMenace merged 4 commits into
masterfrom
feat/api-contract-2026-10

Conversation

@0xFantomMenace

Copy link
Copy Markdown
Member

Adopts the 0xArchive API contract 2026-10-01. Folded into the unreleased 1.12.0; the version is unchanged.

Version selector

  • Every REST request sends 0xArchive-Version: 2026-10-01 (including the raw web3 subscribe requests); OxArchiveWs connects with version=2026-10-01. Exported as API_VERSION and API_VERSION_HEADER.
  • Data quality and client.symbols.list() read the standard { success, data, meta } envelope.
  • Record times that were integer milliseconds are RFC 3339, with the integer in a *Ms field: CVD buckets, HIP-3 oracle reads, Lighter and Robinhood Chain liquidations and liquidation volume, L4 snapshot resting orders (timestamp/timestampMs), and snapshotTs/snapshotTsMs on liquidation levels and trigger-levels history.
  • Lighter and Robinhood Chain replay rows use the live shapes; a tick-granularity checkpoint is converted to an OrderBook for onHistoricalTickData().

Errors

  • OxArchiveError exposes errorCode, status, requestId, param, validValues and the error body. ERROR_CODES, the ErrorCode union, WEBSOCKET_ONLY_ERROR_CODES and isErrorCode() are exported. A non-JSON error body keeps its HTTP status.
  • WebSocket error messages carry errorCode (for example slow_consumer, endpoint_unsupported); ws.onServerError() receives them.

Pagination and meta

  • Paged methods return hasMore (from meta.hasMore) with nextCursor, and meta including meta.symbol and meta.venue. The positions iterators stop when hasMore is false.

Capabilities

  • client.capabilities() returns typed GET /v1/capabilities rows.
  • WS_CHANNEL_CAPABILITIES is one table of every WebSocket channel (venue, datatype, live, replay, bulk replay) mirroring the endpoint; the live and replay checks read it.

Parameters

  • side: 'buy' | 'sell' on trade history and trades.recent() on every venue.
  • triggered on order history (Hyperliquid core, HIP-3, HIP-4).
  • depth on full-depth L2 history; order book history depth documented for every venue.

WebSocket replay

  • L4 replay for HIP-3, Spot and HIP-4 and full-depth replay (orderbook_full, hip3_orderbook_full) are no longer refused: bulk, single-channel, explicit end, speed ignored. Replay is still refused for ticker, all_tickers, spot_orderbook, spot_trades and spot_twap, and live subscription for the replay-only candle and L3 channels.

Verbs

  • trades.history() beside trades.list(), and spot.twap.history() beside spot.twap.bySymbol(). No names were removed.

Docs

  • README sections for the API version, method names, pagination, capabilities, error codes, bulk replay and WebSocket errors; channel tables follow /v1/capabilities; the venue is named Lighter. CHANGELOG 1.12.0 updated.

Testing

  • npm run build, npx tsc --noEmit -p ., npx eslint src/ (0 errors), the package-contents check, and npx vitest run: 364 passed, 9 skipped.
  • tests/api-contract.test.ts covers each item with mocked fetch and a fake socket.
  • tests/live-contract.test.ts runs read-only checks against the live API when OXA_API_KEY is set (skipped otherwise): 9 passed.

…lities

Every REST request sends 0xArchive-Version: 2026-10-01 and the WebSocket
client connects with version=2026-10-01. The SDK parses that version's
shapes: the standard envelope on data quality and /v1/symbols, RFC 3339
record times with integer *Ms fields, and the live payload shapes on
Lighter and Robinhood Chain replay.

- OxArchiveError exposes errorCode, status, requestId, param, validValues
  and the error body; ERROR_CODES and the ErrorCode union list the codes.
  WebSocket error messages carry errorCode, with ws.onServerError().
- Paged methods return hasMore and meta (including meta.symbol and
  meta.venue); the positions iterators stop when hasMore is false.
- client.capabilities() returns typed /v1/capabilities rows.
- trades side (buy or sell) on history and recent, on every venue;
  triggered on order history; depth on full-depth L2 history.
- WebSocket replay of HIP-3, HIP-4 and Spot L4 and of the full-depth
  channels, checked against WS_CHANNEL_CAPABILITIES, one table that
  mirrors /v1/capabilities.
- trades.history() and spot.twap.history() beside the existing names.
- The venue is named Lighter in the README and doc comments.
@nuttykenzo

Copy link
Copy Markdown
Contributor

Target date: no date → 2026-10-08

Date status: Proposed. This is a proposed delivery target; owner confirmation is still required.

Why: K requested a Target date on every active tracked item. This copies the already recorded planning/review date; it does not create owner agreement or change scope, status, priority, ownership, implementation/deployment/sending permission, or any release hold.

The client used the global WebSocket, which Node.js 18 and 20 do not
have, so connect() failed there with "WebSocket is not defined". In
Node.js 24.15 the built-in WebSocket closes the connection (1006) when a
compressed message decompresses to more than about 4 MB, which a BTC L4
snapshot does. In Node.js the client now connects with the ws package,
already a dependency of the SDK, on every version; the built-in
WebSocket is the fallback when ws cannot be loaded. Browsers keep the
built-in WebSocket, and a WebSocket the caller assigns to globalThis is
used as is.

A replay sent before connect() resolved was dropped without an error.
Requests made while the client is connecting or reconnecting are now
queued and sent once the socket opens, and discarded if the first
connect fails. While the client is disconnected they throw an error
that says to call and await connect(); replayStop() and streamStop()
do nothing then, since nothing is running. Subscriptions behave as
before: they are kept and sent on every connect.

- Tests cover the queue, the refusal, a reconnect, a real ws server
  with no global WebSocket, and a 9 MB compressed message.
WS_CHANNEL_CAPABILITIES marked hip4_orderbook, hip4_open_interest and
spot_twap as live. /v1/capabilities says the two HIP-4 channels replay
only and spot_twap neither streams nor replays: the API accepts a
subscription to each but sends nothing on it.

- hip4_orderbook and hip4_open_interest are replay only. A live
  subscription, including through subscribeHip4(), throws before
  sending; read the current book and open interest over REST.
- spot_twap is REST only (client.spot.twap). Live and replay requests
  throw restOnlyError(); the channel name stays so existing code
  compiles. WsLiveOnlyChannel no longer lists it, and the new
  WsRestOnlyChannel does.
- The unit table matches the capabilities rows of 2026-10-04, and the
  live check compares every channel's venue, datatype and modes with
  the endpoint, including channels that no row lists.
- package.json exports give each condition its own declarations:
  import resolves index.d.mts and index.mjs, require index.d.ts and
  index.js. ES module projects using node16 or nodenext resolution
  failed to type-check `import OxArchive from '@0xarchive/sdk'`,
  because the declarations were read as CommonJS. The JavaScript entry
  points are unchanged. repository.url uses the git+https form.
- The README coverage table gives each dataset's first served instant
  from /v1/capabilities instead of month-level dates; Robinhood Chain
  candles are served from 2026-06-26 20:10 UTC; HIP-3 L4 and order
  history from 2026-03-11 01:03 UTC; Spot TWAP is REST only.
- Market counts for Spot and Robinhood Chain are no longer pinned;
  the listing calls return the current set.
- Examples use windows relative to now, so they run on a Free key's
  30-day window. HIP-4 examples look up an open outcome first, HIP-3
  examples use markets that are trading, and every replay example
  awaits connect().
- The Hyperliquid core trades note no longer describes how trades are
  collected; doc comments drop pipeline wording and em dashes.
- README and CHANGELOG 1.12.0 record these changes, the ws package in
  Node.js, the request queue, the channel table and the trade side
  values the API accepts; the CHANGELOG states plain semantic
  versioning.
@0xFantomMenace
0xFantomMenace merged commit 01d7e16 into master Oct 5, 2026
1 check passed
@0xFantomMenace
0xFantomMenace deleted the feat/api-contract-2026-10 branch October 5, 2026 00:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants