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
- Trading signals - Real-time trading signals with entry/target/stop-loss levels ⭐ NEW in v1.12.0
- 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.12.0)
- Trading signals ⭐ NEW - 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.10.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 (v1.12.0) ⭐ NEW
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 examples:
- PHP:
examples/backend-token-proxy.php - Node.js:
examples/backend-token-proxy.js - Python:
examples/backend-token-proxy.py - Go:
examples/backend-token-proxy.go - Java:
examples/backend-token-proxy.java
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)
- 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 - Full Browser Example:
examples/browser-example.html- Complete UI with all features
Framework Examples
- Node.js Example:
examples/node-example.js- Backend usage with automatic token fetching - Next.js App Router Example:
examples/nextjs-app-router/- Full Next.js 15 example with token endpoint, lazy connect, and debug mode
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
Node.js:
cd examples
WIOEX_API_KEY=your-api-key node node-example.jsNext.js:
cd examples/nextjs-app-router
cp .env.example .env.local
# Edit .env.local and add your WIOEX_API_KEY
npm install
npm run dev
# Open http://localhost:3000See examples/nextjs-app-router/README.md 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