WebSocket client for real-time OpenSea marketplace event streaming via the Stream API (Phoenix Channels).
cd packages/stream
pnpm install
pnpm run build # Build with tsup
pnpm run test # Run tests with Vitest
pnpm run lint # Lint with Biome
pnpm run format # Format with Biome
pnpm run check-types # TypeScript type checking| File | Role |
|---|---|
src/client.ts |
OpenSeaStreamClient — main class managing Socket connection, channels, and event subscriptions |
src/types.ts |
All public types: ClientConfig, EventType enum, event payload interfaces (ItemListedEvent, ItemSoldEvent, etc.) |
src/constants.ts |
WebSocket endpoints per network |
src/helpers.ts |
Topic construction for Phoenix channel subscriptions |
src/index.ts |
Public exports |
test/client.spec.ts |
Unit tests with mock WebSocket |
test/helpers.ts |
Test utilities for accessing private client internals (socket, channels) |
test/mock-ws.ts |
Mock WebSocket server for testing |
When reviewing changes to this package, verify:
-
Event type completeness: The
EventTypeenum insrc/types.tsmust match the events published by the Stream API backend (pushed-updates). When a new event type is added server-side, add it to the enum and create a corresponding payload interface andon*method inclient.ts. -
Phoenix protocol compatibility: The client uses the
phoenixnpm package for WebSocket multiplexing. Changes to channel join/leave logic must respect Phoenix channel lifecycle (join → receive ok/error → on events → leave). -
BaseStreamMessageshape: All event payloads extendBaseStreamMessage<Payload>which includesevent_type,version,sent_at, andpayload. Do not change this base shape without coordinating with the backend. -
Browser and Node compatibility: The client detects
window.WebSocketfor browser environments and allows custom transport viaconnectOptions. Changes must not break either environment. -
Unsubscribe cleanup: Each
on*method returns an unsubscribe function that callschannel.leave()and removes the channel from the internal map. Verify new subscription methods follow this pattern.
- ESM-only (
"type": "module"). Use.jsextensions in import paths. - Dual CJS/ESM output via tsup.
- Biome for linting and formatting (config at monorepo root).
- The client auto-connects the socket on the first
on*call — no need to callconnect()explicitly. - Collection slugs are the primary subscription key (one Phoenix channel per collection).
Network.MAINNETis the only supported network. TheapiUrlconfig option allows custom endpoints.