UNPKG

@hackape/tardis-dev

Version:

Convenient access to tick-level historical and real-time cryptocurrency market data via Node.js

79 lines (67 loc) 2.46 kB
import { Filter } from '../types' import { RealTimeFeedBase, MultiConnectionRealTimeFeedBase } from './realtimefeed' export class BybitRealTimeDataFeed extends MultiConnectionRealTimeFeedBase { protected *_getRealTimeFeeds(exchange: string, filters: Filter<string>[], timeoutIntervalMS?: number, onError?: (error: Error) => void) { const linearContractsFilters = filters.reduce( this._only((s) => s.endsWith('USDT')), [] as Filter<string>[] ) const inverseContractsFilters = filters.reduce( this._only((s) => s.endsWith('USDT') === false), [] as Filter<string>[] ) if (linearContractsFilters.length > 0) { yield new BybitSingleConnectionRealTimeDataFeed('realtime_public', exchange, linearContractsFilters, timeoutIntervalMS, onError) } if (inverseContractsFilters.length > 0) { yield new BybitSingleConnectionRealTimeDataFeed('realtime', exchange, inverseContractsFilters, timeoutIntervalMS, onError) } } private _only(filter: (symbol: string) => boolean) { return (prev: Filter<string>[], current: Filter<string>) => { if (!current.symbols || current.symbols.length === 0) { throw new Error('BybitRealTimeDataFeed requires explicitly specified symbols when subscribing to live feed') } const symbols = current.symbols.filter(filter) if (symbols.length > 0) { prev.push({ channel: current.channel, symbols }) } return prev } } } class BybitSingleConnectionRealTimeDataFeed extends RealTimeFeedBase { protected readonly wssURL: string constructor( wsURLSuffix: string, exchange: string, filters: Filter<string>[], timeoutIntervalMS?: number, onError?: (error: Error) => void ) { super(exchange, filters, timeoutIntervalMS, onError) this.wssURL = `wss://stream.bybit.com/${wsURLSuffix}` } protected mapToSubscribeMessages(filters: Filter<string>[]): any[] { const args = filters .map((filter) => { return filter.symbols!.map((symbol) => { const suffix = filter.channel === 'instrument_info' || filter.channel === 'orderBook_200' ? '.100ms' : '' return `${filter.channel}${suffix}.${symbol}` }) }) .flatMap((f) => f) return [ { op: 'subscribe', args } ] } protected messageIsError(message: any): boolean { return message.success === false } }