UNPKG

@wioex/stream-sdk

Version:

WebSocket streaming SDK for real-time WioEX market data

971 lines (732 loc) 26 kB
# @wioex/stream-sdk [![npm version](https://badge.fury.io/js/%40wioex%2Fstream-sdk.svg)](https://www.npmjs.com/package/@wioex/stream-sdk) [![TypeScript](https://img.shields.io/badge/TypeScript-5.3-blue.svg)](https://www.typescriptlang.org/) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/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 - **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.) ```bash npm install @wioex/stream-sdk ``` ### CDN (Browser - No build tools required) **Vanilla JavaScript:** ```html <script src="https://unpkg.com/@wioex/stream-sdk@latest/dist/wioex-stream.min.js"></script> ``` **jQuery Plugin:** ```html <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):** ```html <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: ```bash npm pack @wioex/stream-sdk # Extract dist/ folder and upload to your server ``` > **Complete Browser Guide:** See [docs/BROWSER_GUIDE.md](./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: ```bash export WIOEX_TELEMETRY_DISABLED=1 ``` Or in your code (before importing): ```javascript process.env.WIOEX_TELEMETRY_DISABLED = '1'; // Then import import { WioexStreamClient } from '@wioex/stream-sdk'; ``` Or in browser: ```html <script> window.WIOEX_TELEMETRY_DISABLED = '1'; </script> <script src="path/to/wioex-stream.min.js"></script> ``` Read our [Privacy Policy](https://wioex.com/privacy) for details. ## Quick Start ### Super Simple! Just provide your API key 🎉 **Node.js / Backend:** ```typescript 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):** ```html <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):** ```html <!-- 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: ```typescript 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:** ```typescript 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):** ```javascript // 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):** ```javascript // 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`](./examples/backend-token-proxy.php) - Node.js: [`examples/backend-token-proxy.js`](./examples/backend-token-proxy.js) - Python: [`examples/backend-token-proxy.py`](./examples/backend-token-proxy.py) - Go: [`examples/backend-token-proxy.go`](./examples/backend-token-proxy.go) - Java: [`examples/backend-token-proxy.java`](./examples/backend-token-proxy.java) --- **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](./docs/BROWSER_GUIDE.md) for comprehensive browser usage documentation including CDN, self-hosting, jQuery integration, and framework examples. ## API Reference ### Constructor ```typescript 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: 1s2s4s, linear: 1s2s3s) | **Example:** ```typescript 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:** ```typescript // 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. ```typescript // 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. ```typescript client.disconnect(); ``` #### `subscribe(stocks: string | string[]): void` Subscribe to stock ticker updates. ```typescript 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. ```typescript client.unsubscribe('AAPL'); client.unsubscribe(['AAPL', 'TSLA']); ``` #### `getState(): ConnectionState` Get current connection state. ```typescript const state = client.getState(); // Returns: 'disconnected' | 'connecting' | 'connected' | 'registered' | 'reconnecting' | 'failed' ``` #### `getSubscribedStocks(): string[]` Get list of currently subscribed stocks. ```typescript const stocks = client.getSubscribedStocks(); console.log(stocks); // ['AAPL', 'TSLA', 'GOOGL'] ``` #### `getStats(): ClientStats` Get client statistics. ```typescript 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. ```typescript if (client.isConnected()) { console.log('Connected!'); } ``` #### `updateToken(token: string, expiresAt: number): void` Manually update authentication token (useful for token refresh implementations). ```typescript // 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. ```typescript client.on('connected', () => { console.log('Connected to WioEX stream'); }); ``` #### `registered` Emitted when client is registered with API key. ```typescript client.on('registered', (data) => { console.log('Registered:', data.message); }); ``` #### `subscribed` Emitted when subscribed to stocks. ```typescript client.on('subscribed', (stocks: string[]) => { console.log('Subscribed to:', stocks); }); ``` #### `unsubscribed` Emitted when unsubscribed from stocks. ```typescript client.on('unsubscribed', (stocks: string[]) => { console.log('Unsubscribed from:', stocks); }); ``` #### `ticker` Emitted when ticker data is received. ```typescript client.on('ticker', (data: TickerData) => { console.log(`${data.ticket}: $${data.last}`); }); ``` **TickerData Structure:** ```typescript 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:** ```json { "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): ```javascript 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: ```javascript // 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. ```typescript client.on('error', (error: Error) => { console.error('Error:', error.message); }); ``` #### `disconnected` Emitted when connection is closed. ```typescript client.on('disconnected', (code: number, reason: string) => { console.log(`Disconnected (${code}): ${reason}`); }); ``` #### `reconnecting` Emitted when attempting to reconnect. ```typescript client.on('reconnecting', (attempt: number) => { console.log(`Reconnecting... (attempt ${attempt})`); }); ``` #### `stateChange` Emitted when connection state changes. ```typescript client.on('stateChange', (state: ConnectionState) => { console.log(`State: ${state}`); }); ``` #### `tokenExpiring` Emitted when token is about to expire (before auto-refresh). ```typescript client.on('tokenExpiring', ({ currentToken, expiresAt }) => { console.log(`Token expiring at ${new Date(expiresAt * 1000)}`); }); ``` #### `tokenRefreshed` Emitted when token has been successfully refreshed. ```typescript client.on('tokenRefreshed', ({ token, expiresAt }) => { console.log(`Token refreshed! New expiry: ${new Date(expiresAt * 1000)}`); }); ``` #### `tokenRefreshFailed` Emitted when token refresh fails. ```typescript client.on('tokenRefreshFailed', (error: Error) => { console.error('Token refresh failed:', error.message); }); ``` #### `tokenFetchStarted` Emitted when token fetch starts (from endpoint or API). ```typescript client.on('tokenFetchStarted', (source: 'endpoint' | 'api') => { console.log(`Fetching token from ${source}...`); }); ``` #### `tokenFetchSucceeded` Emitted when token fetch succeeds. ```typescript 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). ```typescript 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 ```json { "action": "register", "token": "your-temporary-token" } ``` **Response:** ```json { "status": "success", "type": "registered", "message": "Client registered successfully" } ``` ### Subscribe ```json { "action": "subscribe", "stocks": ["AAPL", "TSLA", "GOOGL"] } ``` **Response:** ```json { "status": "success", "type": "subscribed", "message": "Subscribed to stocks", "stocks": ["AAPL", "TSLA", "GOOGL"] } ``` ### Ticker Update ```json { "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: ```typescript 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 ```bash # 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 - **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):** 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 **Node.js:** ```bash cd examples WIOEX_API_KEY=your-api-key node node-example.js ``` **Next.js:** ```bash 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:3000 ``` See `examples/nextjs-app-router/README.md` for detailed documentation. ## Documentation - **[BROWSER_GUIDE.md](./docs/BROWSER_GUIDE.md)** - Comprehensive browser usage guide - **[BINARY_PROTOCOL.md](./BINARY_PROTOCOL.md)** - Binary protocol guide (MessagePack) - **[PERFORMANCE.md](./PERFORMANCE.md)** - Performance optimization guide - **[CHANGELOG.md](./CHANGELOG.md)** - Version history and changes ## License MIT License - see [LICENSE](LICENSE) file for details. ## Support - **Documentation:** [https://docs.wioex.com](https://docs.wioex.com) - **API Reference:** [https://api.wioex.com/docs](https://api.wioex.com/docs) - **Issues:** [https://github.com/wioex/wioex-stream-sdk/issues](https://github.com/wioex/wioex-stream-sdk/issues) ## Related Projects - [@wioex/php-sdk](https://github.com/wioex/wioex-php-sdk) - PHP SDK for WioEX API --- Made by [WioEX](https://wioex.com)