π Supercharge your DEX experience with real-time order book data indexing
A high-performance blockchain indexer powered by Ponder that processes events from the ScaleX CLOB DEX (Central Limit Order Book Decentralized Exchange). It also exposes a realβtime WebSocket API so frontβends can stream depth, trades, tickers, and personal order reports without polling.
This indexer is the backbone of the ScaleX CLOB DEX, processing and storing on-chain events in real-time. It maintains a structured database of all trading activities and market data for seamless DeFi operations.
-
πββοΈ PoolManager
- Pool creation & configuration
- Trading pair setup
-
π OrderBook
- π Order placement
- β‘ Order matching
- ποΈ Order cancellation
- π Order updates
-
π° BalanceManager
- π₯ Deposits
- π€ Withdrawals
- π Transfers
- πΈ Fee distribution
The indexer spins up a WebSocket gateway on wss://core-devnet.scalex.money.
| Stream Name | Description |
|---|---|
<symbol>@depth |
Full order book deltas |
<symbol>@depth5@100ms |
Top 5 bids/asks snapshot every 100 ms |
<symbol>@trade |
Individual trade ticks |
<symbol>@kline_1m |
Candlestick data for 1m interval |
<symbol>@miniTicker |
24 h summary: last, high, low, volume |
Subscribe using:
{
"method": "SUBSCRIBE",
"params": ["ethusdc@depth"],
"id": 1
}Unsubscribe with:
{
"method": "UNSUBSCRIBE",
"params": ["ethusdc@depth"],
"id": 2
}List subscriptions:
{ "method": "LIST_SUBSCRIPTIONS", "id": 3 }Connect to:
wss://core-devnet.scalex.money/ws/<walletAddress>
No subscription message is required. You will automatically receive:
Sent when your order is created, filled, or canceled.
{
"e": "executionReport",
"E": 1747466880,
"s": "MWETHMUSDC",
"i": "157",
"S": "SELL",
"o": "MARKET",
"x": "TRADE",
"X": "FILLED",
"q": "1000000000000000000",
"z": "1000000000000000000",
"p": "0",
"L": "1900000000",
"T": 1747466880
}| Field | Description |
|---|---|
| s | Symbol (e.g. MWETHMUSDC) |
| i | Order ID |
| S | Side (BUY/SELL) |
| o | Order type (MARKET/LIMIT) |
| x | Execution type (NEW, TRADE, CANCELED) |
| X | Order status (NEW, FILLED, PARTIALLY_FILLED) |
| q | Total order quantity |
| z | Cumulative filled quantity |
| p | Limit price (if applicable) |
| L | Last executed price |
| T | Timestamp |
Sent when balances change (deposit, withdrawal, fill, lock/unlock).
{
"e": "balanceUpdate",
"E": 1747466880,
"a": "0x9a9f...",
"b": "2149644000",
"l": "0"
}| Field | Description |
|---|---|
| a | Token address |
| b | Available balance (stringified bigint) |
| l | Locked balance (stringified bigint) |
- Connect to wss://core-devnet.scalex.money/ws/
- Place an order β receive executionReport (NEW)
- Order fills β receive executionReport (TRADE) and balanceUpdate
- Cancel an order β receive executionReport (CANCELED)
pnpm ts-node websocket-client.ts
> subscribe gswethgsusdc@depth
> subscribe gswethgsusdc@trade
> user 0x9a9f2ccfde556a7e9ff0848998aa4a0cfd8863aecurl 'http://localhost:42080/api/v3/depth?symbol=ethusdc&limit=20'The indexer provides candlestick data through two endpoints:
# Get historical kline data
curl 'http://localhost:42080/api/kline?symbol=ethusdc&interval=1m&startTime=1746466880000&endTime=1747466880000&limit=500'
# Get mock kline data for testing
curl 'http://localhost:42080/api/kline/mocks?symbol=ethusdc&interval=1m'Parameters:
symbol(required): Trading pair (e.g., 'ethusdc')interval(optional): Time interval - '1m', '5m', '30m', '1h', '1d' (default: '1m')startTime(optional): Start time in milliseconds (default: 0)endTime(optional): End time in milliseconds (default: current time)limit(optional): Maximum number of records (default: 1000)
The kline data follows the standard format:
[
[
1747466820000, // Open time (ms)
"1850.00", // Open
"1855.25", // High
"1849.50", // Low
"1852.75", // Close
"12.35", // Volume
1747466879999, // Close time (ms)
"22865.71", // Quote asset volume
98, // Number of trades
"6.18", // Taker buy base asset volume
"11432.85", // Taker buy quote asset volume
"0" // Unused field
],
// More kline data...
]
| What you can stream | Subscribe with | Notes |
|---|---|---|
| Orderβbook deltas | <symbol>@depth or <symbol>@depth5@100ms |
Emits every time bids or asks change. |
| Live trades | <symbol>@trade |
Tickβbyβtick last price. |
| 1βminute candlesticks | <symbol>@kline_1m |
Any interval supported: 1m, 5m, 1h, 1d β¦ |
| 24 h miniβticker | <symbol>@miniTicker |
Last price / high / low / volume widget. |
This project includes tools for stress testing WebSocket connections and monitoring system performance in real-time.
The stress test tool allows you to simulate multiple WebSocket clients connecting to your server, subscribing to streams, and optionally connecting to user-specific WebSockets.
# Basic usage with 10 clients
pnpm ws-stress-test
# Specify number of clients
pnpm ws-stress-test --clients 50
# Set test duration in seconds
pnpm ws-stress-test --clients 20 --duration 60
# Custom WebSocket URL
pnpm ws-stress-test --url wss://your-websocket-server.com
# Subscribe to specific streams
pnpm ws-stress-test --streams "ethusdc@trade,ethusdc@depth,ethusdc@kline_1m"
# Add delay between client connections (in ms)
pnpm ws-stress-test --delay 200
# Connect to user WebSockets with wallet addresses from a file
pleaTo test user-specific WebSockets, create a text file with one wallet address per line:
0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
0x70997970C51812dc3A010C7d01b50e0d17dc79C8
0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC
Then run the stress test with the --users flag:
pnpm ws-stress-test --users ./user-addresses.txt --clients 10The stress test will cycle through the addresses if there are more clients than addresses.
The metrics dashboard provides real-time monitoring of system performance, database record counts, and WebSocket connection statistics.
# Start the metrics dashboard
pnpm metrics:dashboard
# Watch metrics in real-time (requires ENABLE_SYSTEM_MONITOR=true)
pnpm metrics:watch
# Check current metrics
pnpm metricsThe system monitor is built into the main Ponder process and can be configured with environment variables:
# Enable system monitoring (disabled by default)
ENABLE_SYSTEM_MONITOR=true pnpm dev
# Enable with custom interval (30 seconds by default)
ENABLE_SYSTEM_MONITOR=true SYSTEM_MONITOR_INTERVAL=30 pnpm devEnvironment Variables:
ENABLE_SYSTEM_MONITOR: Set totrueto enable metrics collection (default:false)SYSTEM_MONITOR_INTERVAL: Collection interval in seconds (default:30)
Recommended intervals (use multiples of 10 for best synchronization):
- Development/Testing: 10, 20, or 30 seconds for responsive monitoring
- Production: 30, 60, or 120 seconds to reduce overhead
- Avoid: Non-multiples of 10 (e.g., 15, 25, 45) as they cause timing misalignment
When enabled, metrics are automatically logged to logs/system-metrics.log and can be viewed with the dashboard.
Note: For accurate WebSocket metrics, use the integrated monitoring (
ENABLE_SYSTEM_MONITOR=true pnpm dev) rather than running the system monitor separately (pnpm monitor), since WebSocket connections are only visible within the same process.
- System metrics: CPU usage, memory usage, network connections
- Database statistics: Record counts for orders, trades, balances
- WebSocket metrics: Active connections, messages per second, subscription types
- Performance trends: Memory growth, message throughput
For optimal monitoring during stress tests, run these commands in separate terminals:
# Terminal 1: Start the indexer with monitoring enabled
ENABLE_SYSTEM_MONITOR=true SYSTEM_MONITOR_INTERVAL=10 pnpm dev
# Terminal 2: Launch the metrics dashboard
pnpm metrics:dashboard
# Terminal 3: Run the stress test
pnpm ws-stress-test --clients 50 --duration 300 --users ./user-addresses.txtThis setup allows you to observe how the system performs under load and identify potential bottlenecks or performance issues.
During development, you can use these tools together to:
- Run the indexer with monitoring:
ENABLE_SYSTEM_MONITOR=true pnpm dev - Launch the dashboard with
pnpm metrics:dashboard - Run stress tests with
pnpm ws-stress-test - Use the WebSocket client for manual testing with
pnpm ws-client
This workflow helps ensure your WebSocket server can handle the expected load and provides visibility into system performance.
User streams
Open a second socket to wss://core-devnet.scalex.money/ws/<walletAddress> to receive:
executionReportβ order status & fillsbalanceUpdateβ deposits, withdrawals, fee distributions
No REST auth is required; simply connect to the addressβspecific socket.
Example with the bundled CLI
pnpm ts-node websocket-client.ts
> subscribe ethusdc@depth
> subscribe ethusdc@trade
> list
- πββοΈ Pools: Trading pair configs
- π Orders: Live & historical orders
- π€ Trades: Executed trades
- π OrderBookTrades: Detailed executions
- π Balances: User token holdings
- π Candlestick Data:
π 1m | π 5m | π 30m | π 1h | π 1d
{
id: hex, // π·οΈ Pool address
coin: string, // π± Trading pair (ETH/USDC)
orderBook: hex, // π OrderBook contract
baseCurrency: hex, // π΅ Base token
quoteCurrency: hex, // π‘ Quote token
lotSize: bigint, // π Min order size
maxOrderAmount: bigint, // π Max order size
timestamp: integer // β° Creation time
}{
id: string, // π Unique ID
poolId: hex, // πββοΈ Pool address
orderId: bigint, // π’ Chain order ID
user: hex, // π€ User address
side: string, // π Buy / π Sell
timestamp: integer, // β° Order time
price: bigint, // π° Price
quantity: bigint, // π¦ Quantity
filled: bigint, // β
Filled amount
type: string, // π― Market/Limit
status: string, // π Order status
expiry: integer // β Expiration
}- π¦ Install dependencies:
pnpm install- βοΈ Setup environment:
cp .env.example .env- πββοΈ Launch indexer:
pnpm dev- π° Start the WebSocket CLI (optional):
pnpm ts-node websocket-client.tsKey files for customization:
- πββοΈ
src/poolManager.ts - π
src/index.ts(OrderBook events) - π°
src/balanceManager.ts
Schema modifications: π§ ponder.schema.ts