Research tools for collecting and analyzing data across perp dexs and cexs
Latest Updates:
- ✅ Fixed Binance order book crossing issues (snapshot-based updates)
- ✅ Fixed Lighter market index mapping and incremental updates
- ✅ Added automatic gz compression for capture files
- ✅ Grid extractor uses client timestamps by default (avoids clock skew)
- ✅ PYTH_LAZER symbols normalized (BTC/USD → BTC)
This library provides a standardized, type-safe interface for connecting to various perpetual DEX and CEX WebSocket APIs, as well as ultra-low latency price oracle feeds. It abstracts away the differences between exchanges while providing a unified data model for market data consumption.
- 🔄 Real-time WebSocket connections with automatic reconnection
- 📊 Standardized data types across all DEX and CEX sources
- 🛡️ Full TypeScript support with strict typing
- 🏗️ Extensible architecture for adding new exchanges
- 💪 Robust error handling and connection management
- 📈 Support for order books and trades streaming
- ⚡ Ultra-low latency price feeds via Pyth Lazer
- 📦 Data capture system with automatic compression
- 📊 Grid extraction for time-series analysis
- 🔄 Multi-exchange capture with unified format
yarn installimport { HyperliquidWebSocketClient, MarketDataHandler, Exchange, MarketDataChannel } from 'dex-market-analytics';
// Define your handlers
const handlers: MarketDataHandler = {
onTrade: (trade) => console.log('New trade:', trade),
onOrderBookSnapshot: (snapshot) => console.log('Order book update:', snapshot),
onConnect: () => console.log('Connected'),
onError: (error) => console.error('Error:', error)
};
// Create and connect client
const client = new HyperliquidWebSocketClient(handlers);
client.connect();
// Subscribe to market data
client.subscribe({
exchange: Exchange.HYPERLIQUID,
symbol: 'BTC',
channels: [MarketDataChannel.TRADES, MarketDataChannel.ORDERBOOK]
});import { LighterWebSocketClient, MarketDataHandler, Exchange, MarketDataChannel } from 'dex-market-analytics';
// Define your handlers
const handlers: MarketDataHandler = {
onTrade: (trade) => console.log('New trade:', trade),
onOrderBookSnapshot: (snapshot) => console.log('Order book update:', snapshot),
onConnect: () => console.log('Connected'),
onError: (error) => console.error('Error:', error)
};
// Create and connect client
const client = new LighterWebSocketClient(handlers);
client.connect();
// Subscribe to market data
client.subscribe({
exchange: Exchange.LIGHTER,
symbol: 'BTC',
channels: [MarketDataChannel.TRADES, MarketDataChannel.ORDERBOOK]
});import { EdgeXWebSocketClient, MarketDataHandler, Exchange, MarketDataChannel } from 'dex-market-analytics';
// Define your handlers
const handlers: MarketDataHandler = {
onTrade: (trade) => console.log('New trade:', trade),
onOrderBookSnapshot: (snapshot) => console.log('Order book update:', snapshot),
onConnect: () => console.log('Connected'),
onError: (error) => console.error('Error:', error)
};
// Create and connect client (public WebSocket)
const client = new EdgeXWebSocketClient(handlers);
client.connect();
// Subscribe to market data
client.subscribe({
exchange: Exchange.EDGEX,
symbol: 'BTC',
channels: [MarketDataChannel.TRADES, MarketDataChannel.ORDERBOOK]
});# DEX Examples
yarn example:hyperliquid # Hyperliquid WebSocket
yarn example:lighter # Lighter WebSocket
yarn example:edgex # EdgeX WebSocket
yarn example:aster # Aster WebSocket
yarn example:pacifica # Pacifica WebSocket
yarn example:paradex # Paradex WebSocket
yarn example:apex # ApeX WebSocket
# CEX Examples
yarn example:binance # Binance WebSocket
yarn example:bybit # Bybit WebSocket
# Price Oracle Examples
yarn example:pyth # Pyth SSE (~180ms latency)
yarn example:pyth-ws # Pyth Lazer WebSocket (sub-ms latency)For Pyth Lazer WebSocket with sub-millisecond latency:
# Set your authentication token
export PYTH_LAZER_TOKEN=your-token-here
yarn example:pyth-ws
# Or create a .env file (see .env.example)
cp .env.example .env
# Edit .env with your token
yarn example:pyth-wsThe library uses standardized types that work across all supported DEXs:
-
Trade: Standardized trade dataexchange: Source exchange identifiersymbol: Trading pair/symbolprice: Executed pricesize: Trade sizeside: BUY or SELLtimestamp: Unix timestamptradeId: Unique trade identifier
-
OrderBookSnapshot: Full order book statebids: Array of bid levels (price, size, orderCount)asks: Array of ask levels (price, size, orderCount)timestamp: Snapshot timestampsymbol: Trading pairexchange: Source exchange
-
OrderBookLevel: Individual price levelprice: Price levelsize: Total size at this levelorderCount: Number of orders (optional)
-
MarketDataSubscription: Define what data to receiveexchange: Target exchangesymbol: Trading symbolchannels: Array of data channels (TRADES, ORDERBOOK)
-
MarketDataHandler: Event callbacksonTrade: Handle incoming tradesonOrderBookSnapshot: Handle order book updatesonConnect: Connection establishedonDisconnect: Connection lostonError: Error occurred
Abstract base class providing:
- Automatic reconnection with exponential backoff
- Ping/pong heartbeat management
- Connection state management
- Event-driven architecture
- Subscription tracking
- Mainnet and testnet support
- L2 order book streaming
- Real-time trade data
- Automatic subscription management
- Mainnet WebSocket support
- Order book incremental updates (not snapshots)
- Real-time trade data
- Market index-based subscription system (ETH=0, BTC=1)
- Optional authentication for account-specific channels
- Note: Market indices don't follow typical ordering
- Public and private WebSocket endpoints
- Order book depth levels (15 or 200 levels)
- Real-time trade streams with liquidation tracking
- Ticker data with funding rates
- Contract metadata support
- Automatic ping-pong handling
- Binance-style WebSocket API
- Aggregate trade streams
- Order book depth updates
- 24hr ticker statistics
- Combined and raw stream modes
- Up to 1001x leverage support
- Hyperliquid fork with compatible API
- Order book and trade streaming
- Automatic reconnection support
- STATUS: Not Functional - API Issues
- ApeX Omni DEX WebSocket implementation
- Issue: WebSocket returns "handler not found" errors for all documented channel formats
- Possible causes:
- May require authentication even for public data
- Documentation may be outdated or incorrect
- API endpoint may be non-functional
- Note: Disabled by default in capture config until API issues are resolved
- Symbol format: BTC-USDT
- STATUS: Not Functional - Requires Authentication
- StarkNet-based perpetual DEX
- Issue: Requires bearer token authentication before subscribing
- Order book updates via delta messages
- Trade execution streaming
- Market statistics and funding rates
- Note: Disabled by default in capture config due to auth requirements
- Industry-standard WebSocket API
- Aggregate trades and order book depth
- Mini ticker and 24hr ticker data
- Mark price and funding rate streams
- Multi-stream support
- V5 API WebSocket support
- Order book depth (1, 50, 200, 500 levels)
- Public trade streaming
- Ticker data with funding info
- Kline/candlestick data
- Liquidation tracking
- SSE Implementation (~180ms latency)
- Server-Sent Events via Hermes API
- Price feed streaming with confidence intervals
- Automatic symbol resolution
- WebSocket Implementation (sub-millisecond latency)
- Direct WebSocket connection for ultra-low latency
- Requires authentication token
- High-frequency price updates
- Failover endpoint support
- Environment variable configuration for secure token management
dex-market-analytics/
├── src/
│ ├── types/
│ │ ├── market-data.ts # Standardized types
│ │ ├── hyperliquid.ts # Hyperliquid-specific types
│ │ ├── lighter.ts # Lighter-specific types
│ │ ├── edgex.ts # EdgeX-specific types
│ │ ├── aster.ts # Aster-specific types
│ │ ├── apex.ts # ApeX-specific types
│ │ ├── binance.ts # Binance-specific types
│ │ ├── bybit.ts # Bybit-specific types
│ │ ├── paradex.ts # Paradex-specific types
│ │ ├── pyth-lazer.ts # Pyth SSE types
│ │ └── pyth-lazer-ws.ts # Pyth WebSocket types
│ ├── clients/
│ │ ├── base-websocket-client.ts # Base WebSocket abstraction
│ │ ├── hyperliquid-websocket-client.ts # Hyperliquid implementation
│ │ ├── lighter-websocket-client.ts # Lighter implementation
│ │ ├── edgex-websocket-client.ts # EdgeX implementation
│ │ ├── aster-websocket-client.ts # Aster implementation
│ │ ├── pacifica-websocket-client.ts # Pacifica implementation
│ │ ├── paradex-websocket-client.ts # Paradex implementation
│ │ ├── apex-websocket-client.ts # ApeX implementation
│ │ ├── binance-websocket-client.ts # Binance implementation
│ │ ├── bybit-websocket-client.ts # Bybit implementation
│ │ ├── pyth-lazer-client.ts # Pyth SSE client
│ │ └── pyth-lazer-websocket-client.ts # Pyth WebSocket client
│ ├── examples/
│ │ └── [exchange]-example.ts # Usage examples for each exchange
│ └── index.ts # Main exports
├── dist/ # Compiled JavaScript (generated)
├── .env.example # Environment variables template
├── .gitignore # Git ignore configuration
├── tsconfig.json # TypeScript configuration
└── package.json # Dependencies and scripts
yarn dev- Development mode with auto-reloadyarn build- Compile TypeScript to JavaScriptyarn start- Run compiled applicationyarn type-check- Type-check without compilingyarn clean- Remove build artifactsyarn capture- Run multi-exchange data captureyarn grid- Extract time-series grid from captures
yarn example:hyperliquid- Hyperliquid DEX streamingyarn example:lighter- Lighter DEX streamingyarn example:edgex- EdgeX DEX streamingyarn example:aster- Aster DEX streamingyarn example:pacifica- Pacifica DEX streamingyarn example:paradex- Paradex DEX streamingyarn example:apex- ApeX DEX streamingyarn example:binance- Binance CEX streamingyarn example:bybit- Bybit CEX streamingyarn example:pyth- Pyth SSE price feedsyarn example:pyth-ws- Pyth Lazer WebSocket (ultra-low latency)
To add support for a new DEX:
- Create exchange-specific types in
src/types/{exchange}.ts - Extend
BaseWebSocketClientinsrc/clients/{exchange}-websocket-client.ts - Map exchange data to standardized types
- Add to
Exchangeenum insrc/types/market-data.ts
Example structure:
export class NewExchangeClient extends BaseWebSocketClient {
protected handleMessage(data: WebSocket.Data): void {
// Parse exchange-specific message
// Convert to standardized types
// Call appropriate handlers
}
protected resubscribe(): void {
// Resubscribe after reconnection
}
}See Type Documentation for detailed type definitions and usage.
# Run capture with default configuration
yarn capture
# Environment variables
export PYTH_LAZER_TOKEN=your-token # Required for Pyth LazerFeatures:
- Captures data from all configured exchanges simultaneously
- Automatic file rotation (hourly by default)
- Automatic gz compression of completed files (~90% space savings)
- State management for crash recovery
- Real-time metrics and monitoring
# Extract 1-second grid from captures
yarn grid data/captures/
# Custom period and symbol filter
yarn grid -p 5000 -s BTC data/captures/
# Use exchange timestamps instead of client time
yarn grid --exchange-time data/captures/Features:
- Streaming processing for large datasets
- Handles both .jsonl and .jsonl.gz files
- Client timestamps by default (avoids clock skew)
- Symbol normalization (BTC/USD → BTC)
- CSV output with bid/ask/mid/spread
- Fixed: Order book crossing issue (was treating snapshots as incremental)
- Fixed: Market index mapping (ETH=0, BTC=1, not the reverse)
- Fixed: Incremental updates were treated as snapshots
- Non-functional: API returns "handler not found" for all subscriptions
- Disabled by default in capture config
- Requires authentication: Even for public data
- Disabled by default in capture config
- Symbols include /USD suffix (normalized in grid extraction)
- Requires authentication token
MIT