Package Exports
- @wioex/stream-sdk
 - @wioex/stream-sdk/jquery
 
Readme
@wioex/stream-sdk
WebSocket streaming SDK for real-time WioEX market data. Receive live stock ticker updates with a simple, event-driven API.
Features
- Real-time streaming - WebSocket-based live market data
 - Enhanced reliability - Multi-source failover architecture for improved connection stability (NEW in v1.13.0)
 - Trading signals - Real-time trading signals with entry/target/stop-loss levels
 - High-performance - Optimized for high-frequency data with throttling & batching
 - Multiple stocks - Track up to 50 stocks simultaneously
 - Auto-reconnection - Automatic reconnection with exponential backoff
 - Type-safe - Written in TypeScript with full type definitions
 - Universal - Works in Node.js and browsers
 - Lightweight - ~88KB ESM, ~75KB UMD minified (includes optional MessagePack)
 - Event-driven - Simple EventEmitter-based API
 - Production-ready - Robust error handling and heartbeat mechanism
 - Error reporting - Automatic error tracking with batching & deduplication
 
Latest Features (v1.13.0)
- Enhanced Connection Reliability (NEW) - Multi-source failover architecture with:
- Automatic health monitoring and intelligent switching
 - Improved connection stability and reduced latency
 - Enhanced error handling and recovery mechanisms
 - Message batching and buffering optimizations
 - Performance metrics tracking and monitoring
 
 - Trading signals (v1.12.0) - Subscribe to real-time trading signals with:
- Signal types: BUY, SELL, STRONG_BUY, STRONG_SELL, HOLD
 - Entry price, target price, stop-loss levels
 - Confidence score (0-100%)
 - Signal triggered events (entry/target/stop-loss)
 - Multiple timeframes (5m, 15m, 1h, 4h, 1d, 1w, 1M)
 
 - Debug mode enhancements (v1.11.1) - Console logging now respects debug flag
 - Streamlined message format (v1.11.0) - New type-based format for better performance
 - Browser & jQuery support (v1.10.0) - CDN-ready with jQuery plugin wrapper
 - Binary protocol support (v1.10.0) - Optional MessagePack encoding for 50-60% faster parsing (opt-in)
 
Installation
NPM (Node.js, React, Vue, Angular, etc.)
npm install @wioex/stream-sdkCDN (Browser - No build tools required)
Vanilla JavaScript:
<script src="https://unpkg.com/@wioex/stream-sdk@latest/dist/wioex-stream.min.js"></script>jQuery Plugin:
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script src="https://unpkg.com/@wioex/stream-sdk@latest/dist/wioex-stream.jquery.min.js"></script>Specific Version (Recommended for production):
<script src="https://unpkg.com/@wioex/stream-sdk@1.13.0/dist/wioex-stream.min.js"></script>Self-Hosted
Download from NPM and host on your own server:
npm pack @wioex/stream-sdk
# Extract dist/ folder and upload to your serverComplete Browser Guide: See docs/BROWSER_GUIDE.md for CDN options, self-hosting, jQuery integration, and framework examples.
Anonymous Telemetry
WioEX Stream SDK collects anonymous usage statistics to help us improve the SDK. This happens once on first usage.
What we collect:
- SDK version and type
 - Runtime environment (Node.js/Browser version)
 - Operating system type
 - Installation timestamp
 - Anonymous machine ID (hash-based, no personal info)
 
What we DON'T collect:
- Personal information
 - API keys or tokens
 - IP addresses
 - Business data or stock symbols
 - Any identifiable information
 
Disable telemetry:
Set environment variable:
export WIOEX_TELEMETRY_DISABLED=1Or in your code (before importing):
process.env.WIOEX_TELEMETRY_DISABLED = '1';
// Then import
import { WioexStreamClient } from '@wioex/stream-sdk';Or in browser:
<script>
  window.WIOEX_TELEMETRY_DISABLED = '1';
</script>
<script src="path/to/wioex-stream.min.js"></script>Read our Privacy Policy for details.
Quick Start
Super Simple! Just provide your API key
Node.js / Backend:
import { WioexStreamClient } from '@wioex/stream-sdk';
// Just provide your API key - SDK handles everything automatically!
const client = new WioexStreamClient({
  apiKey: process.env.WIOEX_API_KEY
});
client.on('ticker', (data) => {
  console.log(`${data.ticket}: $${data.last} (${data.changePercent}%)`);
});
// Lazy connect - just subscribe and SDK connects automatically!
client.subscribe(['AAPL', 'TSLA', 'GOOGL']);Browser / Frontend (Vanilla JavaScript):
<script src="https://unpkg.com/@wioex/stream-sdk@latest/dist/wioex-stream.min.js"></script>
<script>
  // Initialize with token endpoint (recommended for browser)
  const client = new WioexStream({
    tokenEndpoint: '/api/stream/token'  // Your backend endpoint
  });
  client.on('ticker', (data) => {
    console.log(`${data.ticket}: $${data.last}`);
  });
  // Lazy connect - just subscribe and SDK connects automatically!
  client.subscribe(['AAPL', 'TSLA']);
</script>Browser / Frontend (jQuery Plugin):
<!-- Load jQuery first -->
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<!-- Load WioEX jQuery plugin -->
<script src="https://unpkg.com/@wioex/stream-sdk@latest/dist/wioex-stream.jquery.min.js"></script>
<script>
  // Initialize with jQuery
  $('#app').wioexStream({
    tokenEndpoint: '/api/stream/token',
    stocks: ['AAPL', 'TSLA', 'GOOGL']
  });
  // Listen to jQuery events
  $('#app').on('wioex:ticker', function(event, data) {
    console.log(`${data.ticket}: $${data.last}`);
  });
</script>Trading Signals
Subscribe to real-time trading signals with entry prices, targets, and stop-loss levels:
import { WioexStreamClient } from '@wioex/stream-sdk';
const client = new WioexStreamClient({
  apiKey: process.env.WIOEX_API_KEY
});
// Subscribe to ticker updates
client.subscribe(['AAPL', 'TSLA']);
// Subscribe to trading signals for same symbols
client.subscribeSignals(['AAPL', 'TSLA']);
// Listen to new signals
client.on('signal', (signal) => {
  console.log(`${signal.symbol} ${signal.signalType} Signal`);
  console.log(`   Entry: $${signal.entryPrice}`);
  console.log(`   Target: $${signal.targetPrice}`);
  console.log(`   Stop Loss: $${signal.stopLoss}`);
  console.log(`   Confidence: ${signal.confidence}%`);
  console.log(`   Reason: ${signal.reason}`);
  console.log(`   Timeframe: ${signal.timeframe}`);
});
// Listen to signal triggers (entry/target/stop-loss hit)
client.on('signalTriggered', (trigger) => {
  console.log(`Signal Triggered: ${trigger.triggerType.toUpperCase()}`);
  console.log(`   ${trigger.symbol} @ $${trigger.triggeredPrice}`);
});
// Signal subscription events
client.on('signalSubscribed', (symbols) => {
  console.log(`Subscribed to signals for: ${symbols.join(', ')}`);
});
client.on('signalError', (error) => {
  console.error('Signal error:', error.message);
});Signal Types:
BUY- Buy signalSELL- Sell signalSTRONG_BUY- Strong buy recommendationSTRONG_SELL- Strong sell recommendationHOLD- Hold position
Trigger Types:
entry- Price reached entry leveltarget- Price reached target (take profit)stop_loss- Price hit stop-loss levelexpired- Signal expired
Available Methods:
client.subscribeSignals(['AAPL', 'TSLA']);        // Subscribe to signals
client.unsubscribeSignals(['AAPL']);              // Unsubscribe from signals
client.getSignalSubscriptions();                   // Get subscribed symbolsIMPORTANT: Browser Security
NEVER expose your API key in browser/frontend code!
If you see your API key in browser DevTools Network tab, you're doing it wrong!
WRONG (API key visible in browser):
// This exposes your API key in browser Network tab!
const client = new WioexStream({
  apiKey: 'your-api-key-here'  // INSECURE!
});CORRECT (API key stays on server):
// API key is safely stored on your backend
const client = new WioexStream({
  tokenEndpoint: '/api/stream/token'  // SECURE!
});Why this matters:
- Anyone can inspect browser Network tab
 - Exposed API keys can be stolen and abused
 - Your account could be compromised
 
How it works:
Browser → Your Backend (/api/stream/token) → WioEX API
  (token)      (api_key)                     (token)Your backend fetches the token using YOUR API key (server-side), then passes only the token to the browser.
Backend example:
What happens behind the scenes:
- SDK automatically fetches a secure token from your backend endpoint
 - Connects to WebSocket stream with the token
 - Your API key is NEVER exposed in browser code (security first!)
 - Token automatically refreshes before expiry
 
Pro Tip: Use
lazyConnect: true(default) so you don't need to callconnect()- just subscribe!
Browser Guide: See docs/BROWSER_GUIDE.md for comprehensive browser usage documentation including CDN, self-hosting, jQuery integration, and framework examples.
API Reference
Constructor
new WioexStreamClient(config: WioexStreamConfig)Configuration Options
| Option | Type | Default | Description | 
|---|---|---|---|
apiKey | 
string | 
Backend only | Backend (Node.js): Your WioEX API key - SDK auto-fetches token | 
token | 
string | 
Frontend only | Frontend (Browser): Secure token from your backend | 
tokenExpiresAt | 
number | 
- | Token expiration Unix timestamp (seconds) | 
tokenEndpoint | 
string | 
- | Backend endpoint URL to fetch token (browser only) | 
tokenFetchHeaders | 
object | 
- | Custom headers for token endpoint request | 
tokenFetchRetry | 
object | 
See below | Token fetch retry configuration | 
onTokenExpiring | 
function | 
- | Async callback to fetch new token on expiry | 
autoRefreshToken | 
boolean | 
true* | 
Auto-refresh token before expiry (*if onTokenExpiring provided) | 
refreshBeforeExpiry | 
number | 
3600000 | 
Refresh token N ms before expiry (default: 1 hour) | 
lazyConnect | 
boolean | 
true | 
Auto-connect on first subscribe (no manual connect() needed) | 
debug | 
boolean | 
false | 
Enable debug logging to console | 
maxSymbols | 
number | 
50 | 
Maximum symbols to track (1-50) | 
autoReconnect | 
boolean | 
true | 
Enable auto-reconnection | 
reconnectDelay | 
number | 
3000 | 
Reconnection delay (ms) | 
maxReconnectAttempts | 
number | 
0 | 
Max reconnect attempts (0 = infinite) | 
streamUrl | 
string | 
Auto | WebSocket URL (auto-generated) | 
errorReportingLevel | 
string | 
'detailed' | 
Error reporting level (none, minimal, standard, detailed) | 
performance | 
object | 
See below | Performance optimization options | 
Authentication:
- Backend (Node.js): Use 
apiKey- SDK automatically fetches and manages tokens - Frontend (Browser): Use 
tokenORtokenEndpoint- Get from your backend (API key blocked for security) 
Token Fetch Retry Options (tokenFetchRetry config)
| Option | Type | Default | Description | 
|---|---|---|---|
maxAttempts | 
number | 
3 | 
Maximum number of retry attempts | 
delay | 
number | 
1000 | 
Initial delay between retries in milliseconds | 
backoff | 
'linear' | 'exponential' | 
'exponential' | 
Backoff strategy (exponential: 1s → 2s → 4s, linear: 1s → 2s → 3s) | 
Example:
const client = new WioexStreamClient({
  tokenEndpoint: '/api/stream/token',
  tokenFetchRetry: {
    maxAttempts: 5,
    delay: 2000,
    backoff: 'exponential',  // 2s → 4s → 8s → 16s → 32s
  },
});Performance Options (performance config)
| Option | Type | Default | Description | 
|---|---|---|---|
tickerThrottle | 
number | 
16 | 
Throttle ticker events (ms). 0 = disabled, 16 = 60 FPS | 
batchTickers | 
boolean | 
false | 
Enable ticker batching mode | 
tickerBatchSize | 
number | 
10 | 
Maximum ticker batch size | 
errorBatchSize | 
number | 
10 | 
Error reporting batch size | 
errorBatchInterval | 
number | 
5000 | 
Error flush interval (ms) | 
errorDeduplication | 
boolean | 
true | 
Enable error deduplication | 
enableStats | 
boolean | 
true | 
Enable stats tracking (disable in production for 5-10% performance gain) | 
useBinaryProtocol | 
boolean | 
false | 
Use binary protocol (MessagePack) for 50-60% faster parsing (opt-in) | 
Performance Presets:
// Default (balanced - 60 FPS throttling)
const client = new WioexStreamClient({ apiKey: 'xxx' });
// High-performance (no throttling, immediate events)
const client = new WioexStreamClient({
  apiKey: 'xxx',
  performance: {
    tickerThrottle: 0,           // No throttling
    errorBatchSize: 1,           // Immediate error reporting
    errorDeduplication: false,   // No deduplication
  }
});
// Production-optimized (maximum performance, minimal overhead)
const client = new WioexStreamClient({
  apiKey: 'xxx',
  performance: {
    enableStats: false,          // Disable stats for 5-10% CPU reduction
    tickerThrottle: 0,           // No throttling
    errorBatchSize: 20,          // Batch errors
  }
});
// Binary protocol (50-60% faster parsing, requires server support)
const client = new WioexStreamClient({
  apiKey: 'xxx',
  performance: {
    useBinaryProtocol: true,     // Enable MessagePack encoding
    enableStats: false,          // Disable stats for extra speed
  }
});
// See BINARY_PROTOCOL.md for comprehensive guide on binary protocol
// High-volume (optimized for charts - 20 FPS batching)
const client = new WioexStreamClient({
  apiKey: 'xxx',
  performance: {
    tickerThrottle: 50,         // 20 FPS
    batchTickers: true,         // Enable batching
    tickerBatchSize: 20,        // Larger batches
  }
});
// Memory-optimized (aggressive batching)
const client = new WioexStreamClient({
  apiKey: 'xxx',
  performance: {
    errorBatchSize: 50,         // Large error batches
    errorBatchInterval: 10000,  // 10s flush interval
  }
});Methods
connect(): Promise<void>
Connect to WioEX WebSocket stream. In Node.js with apiKey, automatically fetches token before connecting.
// Backend (with apiKey) - await to ensure token fetch completes
await client.connect();
// Frontend (with token) - can be called without await
client.connect();disconnect(): void
Disconnect from WebSocket stream.
client.disconnect();subscribe(stocks: string | string[]): void
Subscribe to stock ticker updates.
client.subscribe('AAPL');
client.subscribe(['AAPL', 'TSLA', 'GOOGL']);Throws: Error if attempting to subscribe to more than maxSymbols.
unsubscribe(stocks: string | string[]): void
Unsubscribe from stock ticker updates.
client.unsubscribe('AAPL');
client.unsubscribe(['AAPL', 'TSLA']);getState(): ConnectionState
Get current connection state.
const state = client.getState();
// Returns: 'disconnected' | 'connecting' | 'connected' | 'registered' | 'reconnecting' | 'failed'getSubscribedStocks(): string[]
Get list of currently subscribed stocks.
const stocks = client.getSubscribedStocks();
console.log(stocks); // ['AAPL', 'TSLA', 'GOOGL']getStats(): ClientStats
Get client statistics.
const stats = client.getStats();
console.log(stats);
// {
//   connectedAt: 1704067200000,
//   reconnectAttempts: 0,
//   messagesReceived: 152,
//   messagesSent: 3,
//   tickersReceived: 148,
//   subscribedStocks: ['AAPL', 'TSLA'],
//   state: 'registered'
// }isConnected(): boolean
Check if client is connected.
if (client.isConnected()) {
  console.log('Connected!');
}updateToken(token: string, expiresAt: number): void
Manually update authentication token (useful for token refresh implementations).
// Update token and schedule auto-refresh
client.updateToken(newToken, newExpiresAt);Events
The client extends EventEmitter and emits the following events:
connected
Emitted when WebSocket connection is established.
client.on('connected', () => {
  console.log('Connected to WioEX stream');
});registered
Emitted when client is registered with API key.
client.on('registered', (data) => {
  console.log('Registered:', data.message);
});subscribed
Emitted when subscribed to stocks.
client.on('subscribed', (stocks: string[]) => {
  console.log('Subscribed to:', stocks);
});unsubscribed
Emitted when unsubscribed from stocks.
client.on('unsubscribed', (stocks: string[]) => {
  console.log('Unsubscribed from:', stocks);
});ticker
Emitted when ticker data is received.
client.on('ticker', (data: TickerData) => {
  console.log(`${data.ticket}: $${data.last}`);
});TickerData Structure:
interface TickerData {
  ticket: string;        // Stock symbol
  last: string;          // Last price
  open: string;          // Opening price
  high: string;          // High price
  low: string;           // Low price
  volume: string;        // Trading volume
  bid: string;           // Bid price
  ask: string;           // Ask price
  change: string;        // Price change
  changePercent: string; // Change percentage
  timestamp: number;     // Unix timestamp
}Message Format
WebSocket Ticker Updates
WioEX Stream uses a streamlined type-based message format for real-time ticker updates.
Message Structure:
{
  "type": "ticker",
  "data": {
    "ticket": "AAPL",
    "last": "150.25",
    "open": "149.80",
    "high": "151.00",
    "low": "149.50",
    "volume": "52847100",
    "bid": "150.20",
    "ask": "150.30",
    "change": "0.45",
    "changePercent": "0.30",
    "timestamp": 1697294400
  }
}Custom WebSocket Implementation
If you're building a custom WebSocket client (not using this SDK):
const WebSocket = require('ws');
const ws = new WebSocket('wss://stream.wioex.com/...');
ws.on('message', (data) => {
  const message = JSON.parse(data);
  if (message.type === 'ticker') {
    const ticker = message.data;
    console.log(`${ticker.ticket}: $${ticker.last} (${ticker.changePercent}%)`);
  }
});Benefits of v2 Format
- 37% smaller payload with MessagePack binary protocol
 - 15-20% faster parsing (reduced nesting depth)
 - Enhanced reliability with improved connection stability
 - More extensible for future message types
 - Cleaner code and better developer experience
 
Migration from v1.10.0
Breaking Change: If updating from v1.10.0 or earlier, update your custom implementations:
// v1.10.0 (OLD - No longer supported)
if (message.sarex && message.sarex.ticker) {
  const ticker = message.sarex.ticker;
}
// v1.11.0+ (NEW - Required)
if (message.type === 'ticker') {
  const ticker = message.data;
}Note: The official SDK handles this automatically - just update to v1.11.0+
error
Emitted when an error occurs.
client.on('error', (error: Error) => {
  console.error('Error:', error.message);
});disconnected
Emitted when connection is closed.
client.on('disconnected', (code: number, reason: string) => {
  console.log(`Disconnected (${code}): ${reason}`);
});reconnecting
Emitted when attempting to reconnect.
client.on('reconnecting', (attempt: number) => {
  console.log(`Reconnecting... (attempt ${attempt})`);
});stateChange
Emitted when connection state changes.
client.on('stateChange', (state: ConnectionState) => {
  console.log(`State: ${state}`);
});tokenExpiring
Emitted when token is about to expire (before auto-refresh).
client.on('tokenExpiring', ({ currentToken, expiresAt }) => {
  console.log(`Token expiring at ${new Date(expiresAt * 1000)}`);
});tokenRefreshed
Emitted when token has been successfully refreshed.
client.on('tokenRefreshed', ({ token, expiresAt }) => {
  console.log(`Token refreshed! New expiry: ${new Date(expiresAt * 1000)}`);
});tokenRefreshFailed
Emitted when token refresh fails.
client.on('tokenRefreshFailed', (error: Error) => {
  console.error('Token refresh failed:', error.message);
});tokenFetchStarted
Emitted when token fetch starts (from endpoint or API).
client.on('tokenFetchStarted', (source: 'endpoint' | 'api') => {
  console.log(`Fetching token from ${source}...`);
});tokenFetchSucceeded
Emitted when token fetch succeeds.
client.on('tokenFetchSucceeded', ({ token, expiresAt, source }) => {
  console.log(`Token fetched from ${source}`);
  console.log(`Expires at: ${new Date(expiresAt * 1000)}`);
});tokenFetchFailed
Emitted when token fetch fails (will retry if configured).
client.on('tokenFetchFailed', (error: Error, attempt: number, willRetry: boolean) => {
  console.error(`Token fetch failed (attempt ${attempt}):`, error.message);
  if (willRetry) {
    console.log('Will retry...');
  }
});WebSocket Protocol
The SDK communicates with WioEX WebSocket API using JSON messages:
Connection
wss://stream.wioex.com/rs/i/{max_symbols}/websocketRegistration
{
  "action": "register",
  "token": "your-temporary-token"
}Response:
{
  "status": "success",
  "type": "registered",
  "message": "Client registered successfully"
}Subscribe
{
  "action": "subscribe",
  "stocks": ["AAPL", "TSLA", "GOOGL"]
}Response:
{
  "status": "success",
  "type": "subscribed",
  "message": "Subscribed to stocks",
  "stocks": ["AAPL", "TSLA", "GOOGL"]
}Ticker Update
{
  "sarex": {
    "_p": { "e": "d" },
    "ticker": {
      "ticket": "AAPL",
      "last": "185.25",
      "open": "183.50",
      "high": "186.00",
      "low": "183.00",
      "volume": "52478963",
      "bid": "185.20",
      "ask": "185.30",
      "change": "1.75",
      "changePercent": "0.95",
      "timestamp": 1704067200000
    }
  }
}TypeScript Support
The SDK is written in TypeScript with full type definitions included:
import type {
  WioexStreamClient,
  WioexStreamConfig,
  TickerData,
  ConnectionState
} from '@wioex/stream-sdk';
// Full IntelliSense and type checking
const client = new WioexStreamClient({
  apiKey: process.env.WIOEX_API_KEY,
  maxSymbols: 50
});
client.on('ticker', (data: TickerData) => {
  // TypeScript auto-complete for all properties
  console.log(data.ticket, data.last, data.changePercent);
});All types are automatically available when you install the package - no @types/* package needed!
Browser Support
The SDK works in all modern browsers that support WebSocket:
- Chrome 16+
 - Firefox 11+
 - Safari 7+
 - Edge 12+
 - Opera 12.1+
 
Node.js Support
Requires Node.js 16 or higher.
Development
# Install dependencies
npm install
# Build the package
npm run build
# Run linter
npm run lint
# Run tests
npm test
# Development mode (watch)
npm run devExamples
See the examples/ directory for complete examples:
Browser Examples
- Simple Vanilla JS: 
examples/simple-vanilla.html- Minimal 100-line example, copy-paste ready - jQuery Plugin: 
examples/jquery-example.html- jQuery plugin integration with Bootstrap UI - Complete Browser Example: 
examples/browser-example.html- Complete UI with all features - PHP Backend Proxy: 
examples/backend-token-proxy.php- Secure token endpoint example 
Quick Start
Simple Vanilla JS (Easiest):
- Build the package: 
npm run build - Open 
examples/simple-vanilla.htmlin a browser - Works with token endpoint or pre-fetched token
 
jQuery Plugin:
- Build the package: 
npm run build - Open 
examples/jquery-example.htmlin a browser - jQuery-friendly API with event delegation
 
PHP Backend Setup:
# Set up PHP backend proxy
cp examples/backend-token-proxy.php /path/to/your/backend/
# Set your WIOEX_API_KEY environment variable
export WIOEX_API_KEY="your-api-key"
# Or add to your .env fileSee examples/backend-token-proxy.php for detailed documentation.
Documentation
- BROWSER_GUIDE.md - Comprehensive browser usage guide
 - BINARY_PROTOCOL.md - Binary protocol guide (MessagePack)
 - PERFORMANCE.md - Performance optimization guide
 - CHANGELOG.md - Version history and changes
 
License
MIT License - see LICENSE file for details.
Support
- Documentation: https://docs.wioex.com
 - API Reference: https://api.wioex.com/docs
 - Issues: https://github.com/wioex/wioex-stream-sdk/issues
 
Related Projects
- @wioex/php-sdk - PHP SDK for WioEX API
 
Made by WioEX