JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 183
  • Score
    100M100P100Q101937F
  • License MIT

WebSocket streaming SDK for real-time WioEX market data

Package Exports

  • @wioex/stream-sdk
  • @wioex/stream-sdk/jquery

Readme

@wioex/stream-sdk

npm version TypeScript License: MIT

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-sdk

CDN (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 server

Complete 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=1

Or 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 signal
  • SELL - Sell signal
  • STRONG_BUY - Strong buy recommendation
  • STRONG_SELL - Strong sell recommendation
  • HOLD - Hold position

Trigger Types:

  • entry - Price reached entry level
  • target - Price reached target (take profit)
  • stop_loss - Price hit stop-loss level
  • expired - Signal expired

Available Methods:

client.subscribeSignals(['AAPL', 'TSLA']);        // Subscribe to signals
client.unsubscribeSignals(['AAPL']);              // Unsubscribe from signals
client.getSignalSubscriptions();                   // Get subscribed symbols

IMPORTANT: 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:

  1. SDK automatically fetches a secure token from your backend endpoint
  2. Connects to WebSocket stream with the token
  3. Your API key is NEVER exposed in browser code (security first!)
  4. Token automatically refreshes before expiry

Pro Tip: Use lazyConnect: true (default) so you don't need to call connect() - 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 token OR tokenEndpoint - 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}/websocket

Registration

{
  "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 dev

Examples

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):

  1. Build the package: npm run build
  2. Open examples/simple-vanilla.html in a browser
  3. Works with token endpoint or pre-fetched token

jQuery Plugin:

  1. Build the package: npm run build
  2. Open examples/jquery-example.html in a browser
  3. 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 file

See examples/backend-token-proxy.php for detailed documentation.

Documentation

License

MIT License - see LICENSE file for details.

Support


Made by WioEX