Day’s Work: NATS Event Publishing and TypeScript Scanner Service Foundation
Published:
TL;DR
Today’s development session focused on two major milestones:
- NATS Event Publishing: Successfully integrated NATS JetStream event publishing into the quote-service with real-time market data distribution
- Scanner Service Foundation: Created TypeScript scanner-service stub at
ts/apps/scanner-serviceto scan for trading opportunities
The scanner-service will initially be implemented in TypeScript for rapid development and testing, with a high-performance Rust version planned for production deployment.
1. NATS Event Publishing in Quote-Service
Overview
The quote-service now publishes real-time market events to NATS JetStream, enabling event-driven architecture for trading strategies, monitoring systems, and analytics services.
Quote-Service Summary
The SolRoute Quote Service is a high-performance HTTP service that provides instant DEX quotes by periodically caching the best routes for token pair trades. Instead of querying DEX pools in real-time (which takes 15-30 seconds), the service maintains up-to-date cached quotes and returns them in milliseconds.
Key Features:
- Instant Responses: Returns cached quotes in milliseconds instead of 15-30 seconds
- Multi-Protocol Support: Queries Raydium (AMM, CLMM, CPMM), PumpSwap, Meteora DLMM, and Whirlpool
- Real-Time Updates: WebSocket subscriptions for live pool state changes
- External Quote APIs: Integration with Jupiter, DFlow, OKX, BLXR, and QuickNode
- Oracle Integration: Pyth Network integration for SOL/USD and LST token pricing
- Dynamic Pair Management: REST API to add/remove token pairs on-the-fly
- LST Token Support: Pre-configured with 12 popular liquid staking tokens
- Market Events: Publishes real-time market data to NATS JetStream
- Production Observability: Structured logging, Prometheus metrics, and OpenTelemetry tracing
Event Types Published
The quote-service now publishes the following event types to NATS:
PriceUpdateEvent
Published when token price changes are detected.
Subject: market.price.update
Example:
{
"eventType": "PriceUpdate",
"timestamp": "2025-12-09T10:30:45Z",
"inputMint": "So11111111111111111111111111111111111111112",
"outputMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"protocol": "RaydiumAmm",
"poolId": "58oQChx4yWmvKdwLLZzBi4ChoCc2fqCUWBkwMihLYQo2",
"oldPrice": "195500000000",
"newPrice": "195750000000",
"priceChange": "250000000",
"percentChange": 0.128,
"inputSymbol": "SOL",
"outputSymbol": "USDC",
"slot": 285432156
}
SpreadUpdateEvent
Published when price spread between DEXes exceeds threshold (default: 1.0%).
Subject: market.spread.update
LargeTradeEvent
Published when a trade exceeds the configured USD threshold (default: $10,000).
Subject: market.trade.large
LiquidityUpdateEvent
Published when pool liquidity is scanned or changes.
Subject: market.liquidity.update
VolumeSpikeEvent
Published when update frequency exceeds threshold (indicates high trading activity).
Subject: market.volume.spike
Default Threshold: 10 updates/minute
PoolStateChangeEvent
Published when pool state changes (new pool, update, removal).
Subject: market.pool.statechange
SlotUpdateEvent
Published Solana slot updates (every 100 slots to reduce noise).
Subject: market.slot.update
Grafana Dashboard: Events by Type
To monitor the event publishing system, I’ve set up a comprehensive Grafana dashboard showing events by type:

The dashboard visualizes:
- Total events published by event type (PriceUpdate, SpreadUpdate, LiquidityUpdate, etc.)
- Publishing errors for troubleshooting
- Real-time event rate to monitor system health
- Event distribution to understand market activity patterns
Configuration
Command-line flags:
./quote-service \
-nats="nats://localhost:4222" \
-largeTradeThreshold=10000 \
-volumeSpikeThreshold=10 \
-spreadThreshold=1.0
| Flag | Description | Default |
|---|---|---|
-nats | NATS server URL (empty to disable) | nats://localhost:4222 |
-largeTradeThreshold | Large trade threshold in USD | 10000 |
-volumeSpikeThreshold | Updates per minute for spike detection | 10 |
-spreadThreshold | Spread alert threshold (percent) | 1.0 |
Disable market events:
./quote-service -nats=""
Monitoring Endpoints
Event stats endpoint:
GET /events/stats
Response:
{
"enabled": true,
"nats_connected": true,
"nats_servers": 1,
"nats_url": "nats://localhost:4222",
"tracked_pairs": 24,
"last_slot": 285432245,
"large_trade_threshold_usd": 10000,
"volume_spike_threshold": 10,
"spread_threshold_percent": 1.0
}
Prometheus metrics:
market_events_published_total{event_type}- Total events publishedmarket_events_publish_errors_total{event_type}- Publishing errorsmarket_events_marshal_errors_total{event_type}- JSON marshaling errorsmarket_events_enabled- Whether events are enabled (0 or 1)nats_connections_total{status}- NATS connection attempts
Performance Characteristics
- Async Publishing: Events published in goroutines to avoid blocking quote requests
- Zero Latency Impact: Event publishing doesn’t affect quote response times
- Memory Storage: Uses NATS memory storage for sub-millisecond event delivery
- Automatic Reconnection: NATS client automatically reconnects on connection loss
2. TypeScript Scanner Service Foundation
Overview
Created a new TypeScript service stub at C:\Trading\solana-trading-system\ts\apps\scanner-service that will consume market events from NATS and scan for trading opportunities.
Why TypeScript First?
The scanner-service will be implemented in TypeScript initially for several reasons:
- Rapid Development: TypeScript allows for faster iteration during development
- Rich Ecosystem: Access to extensive npm packages for market analysis
- Easy Integration: Seamless integration with existing TypeScript services
- Prototyping: Test trading strategies and algorithms quickly
- Team Collaboration: Easier for team members to contribute and review
Rust Version Planned
Once the TypeScript version is stable and trading strategies are validated, we’ll implement a high-performance Rust version for production:
- Performance: Sub-millisecond latency for opportunity detection
- Concurrency: Efficient parallel processing of market events
- Memory Efficiency: Lower resource usage for long-running processes
- Type Safety: Compile-time guarantees for critical trading logic
- System Integration: Direct integration with Solana RPC and DEX protocols
Scanner Service Responsibilities
The scanner-service will:
- Consume Market Events: Subscribe to NATS JetStream for real-time market data
- Detect Opportunities: Analyze spreads, price movements, and liquidity changes
- Strategy Execution: Implement various trading strategies:
- Arbitrage: Cross-DEX price differences
- Market Making: Provide liquidity and earn fees
- Trend Following: Momentum-based trading
- Mean Reversion: Price deviation from moving averages
- Risk Management: Position sizing, stop-loss, and exposure limits
- Performance Tracking: Monitor strategy profitability and execution quality
Integration with System Architecture
┌─────────────────────────────────────────────────────────┐
│ system-initializer │
│ - Creates NATS JetStream streams (EVENTS_*, MARKET) │
│ - Sets up priority-based event infrastructure │
└────────────────┬────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ quote-service │
│ - Fetches LST prices from Pyth oracles │
│ - Publishes market events to NATS │
│ - Provides instant cached quotes │
└────────────────┬────────────────────────────────────────┘
│
▼ (publishes events)
┌─────────────────────────────────────────────────────────┐
│ NATS JetStream │
│ - market.price.update │
│ - market.spread.update │
│ - market.trade.large │
│ - market.liquidity.update │
│ - market.volume.spike │
└────────────────┬────────────────────────────────────────┘
│
▼ (subscribes to events)
┌─────────────────────────────────────────────────────────┐
│ scanner-service (TypeScript) │
│ - Subscribe to all market.* events │
│ - Detect arbitrage opportunities │
│ - Identify trading signals │
│ - Publish opportunity events │
│ - Monitor strategy performance │
└────────────────┬────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Trading Execution │
│ - Execute trades via Solana transactions │
│ - Manage positions and risk │
│ - Track P&L and performance │
└─────────────────────────────────────────────────────────┘
Development Roadmap
Phase 1: TypeScript Implementation (Current)
- ✅ Service stub created
- 🚧 NATS event subscription
- 🚧 Basic arbitrage detection
- 🚧 Strategy framework
- 🚧 Performance monitoring
Phase 2: Strategy Development
- Cross-DEX arbitrage
- LST premium trading
- Market making algorithms
- Risk management system
Phase 3: Production Hardening
- Error handling and recovery
- Performance optimization
- Comprehensive testing
- Production deployment
Phase 4: Rust Migration
- Port validated strategies to Rust
- Performance benchmarking
- Gradual rollout
- Side-by-side comparison
Impact and Next Steps
What This Enables
Today’s work creates the foundation for event-driven trading:
- Real-Time Market Data: Quote-service broadcasts all market changes via NATS
- Decoupled Architecture: Scanner-service operates independently, consuming events
- Scalable Design: Multiple scanner instances can process different strategies
- Observable System: Grafana dashboards provide full visibility into event flow
Integration Benefits
The event publishing system provides several key benefits:
┌──────────────────────────────────────────────────────┐
│ Benefits of Event Architecture │
├──────────────────────────────────────────────────────┤
│ │
│ 1. Decoupling: Services communicate via events │
│ 2. Scalability: Add consumers without changing │
│ producers │
│ 3. Reliability: NATS provides guaranteed delivery │
│ 4. Flexibility: Easy to add new event types │
│ 5. Observability: Monitor entire data flow │
│ │
└──────────────────────────────────────────────────────┘
Next Steps
- Complete Scanner TypeScript Implementation:
- NATS event subscription and processing
- Arbitrage opportunity detection algorithm
- Strategy pattern implementation
- Performance metrics and monitoring
- Strategy Development:
- Cross-DEX arbitrage strategy
- LST premium capture strategy
- Volume spike momentum strategy
- Mean reversion strategy
- Testing and Validation:
- Backtest strategies on historical data
- Paper trading with live events
- Performance analysis and optimization
- Risk management validation
- Production Deployment:
- Deploy TypeScript scanner to production
- Monitor strategy performance
- Iterate and improve based on real data
- Plan Rust migration for proven strategies
- Rust High-Performance Version:
- Design Rust scanner architecture
- Port validated TypeScript strategies
- Performance benchmarking
- Gradual migration to production
Conclusion
Today’s work represents a significant milestone in building the Solana trading system:
- Event Publishing: Quote-service now broadcasts real-time market data to NATS with full observability
- Scanner Foundation: Created TypeScript scanner-service stub as the foundation for trading opportunity detection
- Development Strategy: TypeScript-first approach for rapid iteration, followed by Rust for production performance
The system now has a complete event-driven architecture enabling sophisticated trading strategies with real-time market data and comprehensive monitoring.
Related Posts:
- Getting Started: Building a Solana Trading System - Project overview
- System Initializer Rename, LST Support, and Market Events - Previous market events work
- Building a Cross-Language Event System - NATS JetStream implementation
Technical Documentation:
Connect
- GitHub: github.com/guidebee
- LinkedIn: linkedin.com/in/guidebee
This is post #6 in the Solana Trading System development series. Follow along as I document the journey from working prototypes to production HFT system.
