Skip to content

Support live Lighter WebSocket channels (1.11.0) - #11

Merged
0xFantomMenace merged 4 commits into
masterfrom
lighter-live-websocket
Sep 25, 2026
Merged

0xFantomMenace merged 4 commits into
masterfrom
lighter-live-websocket

Conversation

@0xFantomMenace

@0xFantomMenace 0xFantomMenace commented Sep 25, 2026 •

Copy link
Copy Markdown
Member

Summary

Live subscriptions now work for four Lighter channels: lighter_orderbook, lighter_trades, lighter_open_interest and lighter_funding. lighter_candles and lighter_l3_orderbook stay replay-only, and replay of all six Lighter channels is unchanged.

Client

  • subscribe() and subscribe_async() take an interval_ms keyword for lighter_orderbook. Books default to one per second; 100 to 5000 ms is accepted. The SDK raises ValueError with the server's wording if it is passed on another channel or is out of range, and with its own message if it is not an integer (the server ignores such a subscribe without replying). It is re-sent on reconnect, and a later subscribe without it goes back to the default, which matches how the server replaces a subscription.
  • Live Lighter subscriptions are tracked by the uppercase symbol, as the server treats them, so subscribing as btc and unsubscribing as BTC removes the subscription and it is not restored on reconnect.
  • New helpers: subscribe_lighter_orderbook(coin, interval_ms=None), subscribe_lighter_trades, subscribe_lighter_open_interest, subscribe_lighter_funding and the matching unsubscribe_* methods.
  • New handlers: on_lighter_orderbook, on_lighter_trades and on_lighter_market_context. When the first two are set they take precedence over on_orderbook and on_trades, so Lighter BTC is not mixed up with Hyperliquid BTC. When they are not set, Lighter books and trades still reach the generic handlers.

Types

  • LighterLiveTrade models one live trade leg: two legs per trade share tid, users holds the Lighter account index, and the fee fields and dir are always null.
  • LighterMarketContext and LighterMarketContextUpdate model the message that both lighter_open_interest and lighter_funding carry. Fields use the SDK's snake_case names, and the wire camelCase keys are accepted as aliases.
  • Live books decode to the existing OrderBook.
  • New Trade.account_index field. Live Lighter legs set it, and so do Lighter REST trades, which already return account_index.
  • symbol added to WsSubscribed, WsUnsubscribed and WsData.

Docs and release

  • The README WebSocket section has a new "Live Lighter.xyz Data" section covering payloads, the interval, lag notices and the two-legs-per-trade counting rule.
  • The Lighter channel table and the OI and funding replay note are corrected.
  • CHANGELOG entry and version bump to 1.11.0.

Checks

  • pytest (Python 3.12): 85 passed. This includes new tests for subscribe serialization with and without interval_ms, boundary and rejection cases, case-insensitive subscription tracking, the replay-only rules, re-sending on reconnect, handler precedence and fallback, and parsing of real production frames for all three payload types.
  • tests/test_websocket_capabilities.py on Python 3.9: 60 passed.
  • ruff check oxarchive tests and mypy oxarchive: no new findings compared with master. The existing findings are unchanged.
  • python -m build: sdist and wheel build. I reproduced the package-contents workflow on a clean clone, with stray files planted as the workflow does. Every packaged file is tracked source or build metadata.
  • Ran the branch against wss://api.0xarchive.io/ws:
    • Subscribes were acked with uppercase symbols.
    • Books had 20 levels per side with n=1. BTC arrived about every 250 ms with interval_ms=250 and ETH about once a second by default.
    • Every trade came as two legs, with exactly one taker leg per tid.
    • Market context arrived on both channels.
    • The server's interval_ms error messages match the client-side ones for a wrong channel and an out-of-range value.
    • A btc subscribe is acked as BTC, and a BTC unsubscribe stops it.

lighter_orderbook, lighter_trades, lighter_open_interest and lighter_funding
now accept live subscriptions. lighter_candles and lighter_l3_orderbook stay
replay-only, and replay of all six channels is unchanged.

- subscribe() and subscribe_async() take an interval_ms keyword for
  lighter_orderbook (100 to 5000 ms, one book a second when omitted). It is
  validated before anything is sent and re-sent on reconnect.
- subscribe_lighter_* / unsubscribe_lighter_* helpers.
- on_lighter_orderbook, on_lighter_trades and on_lighter_market_context
  handlers, so Lighter BTC is not mixed up with Hyperliquid BTC. Lighter
  books and trades still reach on_orderbook / on_trades when the dedicated
  handlers are not set.
- Typed live payloads: LighterLiveTrade, LighterMarketContext and
  LighterMarketContextUpdate. Live trade legs map the Lighter account index
  to the new Trade.account_index field, which Lighter REST trades also carry.
- symbol on WsSubscribed, WsUnsubscribed and WsData.
- README WebSocket section, CHANGELOG and version 1.11.0.
- Live Lighter subscriptions are keyed by the uppercase symbol, as the server
  treats them. Subscribing as btc and unsubscribing as BTC now removes the
  subscription and its interval_ms, so a reconnect does not restore it, and a
  resubscribe in another case replaces the earlier interval.
- A non-integer interval_ms (for example 250.0 or True) raises "interval_ms
  must be an integer number of milliseconds" instead of the out-of-range
  message. Out-of-range integers keep the server's wording.
… versions

The README listed the Hyperliquid open_interest and funding WebSocket
channels as replay only. Both stream live as well, so the channel table,
the replay section and the real-time streaming section now say so and show
how to subscribe. HIP-3 wording is unchanged.

The 1.11.0 changelog entry now states that 1.7.1 through 1.10.0 were not
published to PyPI, so upgrading from PyPI goes straight from 1.7.0 to 1.11.0.
The server has discontinued WebSocket bulk streaming and answers
{"op": "stream"} with an error that points to the S3 Parquet bulk export.
stream(), multi_stream() and stream_stop() stay for compatibility but now
emit a DeprecationWarning, and their docstrings say the call returns the
server's error and that large downloads use the bulk export at
https://0xarchive.io/data. The bulk stream handler setters and message
models are marked deprecated with them, and the bulk streaming example is
gone from the module docstring.

The WsChannel docstring now lists Hyperliquid open_interest and funding as
live and replayable. The HIP-3 wording is unchanged. The README drops the
"replay/stream" wording and notes that bulk streaming is discontinued.
@0xFantomMenace
0xFantomMenace merged commit 62c8688 into master Sep 25, 2026
1 check passed
@0xFantomMenace
0xFantomMenace deleted the lighter-live-websocket branch September 29, 2026 00:06
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.

1 participant