Skip to main content
Lighter exposes a native WebSocket endpoint at wss://mainnet.zklighter.elliot.ai/stream. The SDK discovers this URL from the wsUrl field in the GET /providers response. If you’re using the SDK, see Streaming instead.

SDK Channel Mapping

The SDK’s LighterWsProvider maps between normalized channel names and Lighter-native channels:
SDK channelLighter channelAuth requiredSDK event type
pricesmarket_stats/all (uses last_trade_price)NoPricesResponse
orderbookorder_book/<market_id>NoOrderbookResponse
orderUpdatesaccount_all_orders/<account_index>Yes{ openOrders, triggerOrders, terminated }
fillsaccount_all_trades/<account_index>NoFill[]
positionsaccount_all_positions/<account_index>YesPosition[]
Lighter does not expose a live OHLC channel. The SDK returns a no-op unsubscribe for candle subscriptions so chart UIs (rendering from REST history + price ticks) are not disrupted by a thrown error on every mount.

Authenticated channels

Two channels (orderUpdates, positions) require a Lighter auth token on every subscribe message and on every reconnect. fills is unauthenticated. The token is supplied through the authProvider option on lighterWsProvider, registered in the PerpsWsClient’s wsProviders map:
import { createPerpsClient, PerpsWsClient } from '@lifi/perps-sdk';
import { lighterWsProvider } from '@lifi/perps-sdk-provider-lighter';

const client = createPerpsClient({ integrator: 'my-app', apiKey: '...' });

const ws = new PerpsWsClient(client, {
  wsProviders: {
    lighter: lighterWsProvider({
      // Returns a fresh Lighter auth token for the given L1 address, or
      // undefined if no API key is registered. Called both on initial
      // subscribe and on every reconnect — must always return a token valid
      // for at least the next few minutes.
      authProvider: (address) => getLighterAuthToken(address),
    }),
  },
});

await ws.subscribe(
  { channel: 'orderUpdates', dex: 'lighter', address: userAddress },
  (event) => {
    // event.data: { openOrders, triggerOrders, terminated }
  }
);
Without an authProvider, subscribing to an authenticated channel throws at subscribe time. The callback returning undefined (meaning no API key is registered) likewise prevents the subscription from succeeding.

Keepalive

The SDK sends a ping frame every 30 seconds to keep the connection alive.

Per-subscription dex field

When subscribing across providers, the per-subscription field that selects the venue is named dex (not provider). For Lighter the value is lighter for the default sub-venue.