UNPKG

tardis-dev

Version:

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

113 lines 4.05 kB
import { MultiConnectionRealTimeFeedBase, RealTimeFeedBase } from "./realtimefeed.js"; const BULLISH_SUBSCRIPTION_TARGETS = { V1TALevel2: { topic: 'l2Orderbook', path: '/trading-api/v1/market-data/orderbook', symbolParam: 'symbol' }, V1TALevel1: { topic: 'l1Orderbook', path: '/trading-api/v1/market-data/orderbook', symbolParam: 'symbol' }, V1TAAnonymousTradeUpdate: { topic: 'anonymousTrades', path: '/trading-api/v1/market-data/trades', symbolParam: 'symbol' }, V1TATickerResponse: { topic: 'tick', path: '/trading-api/v1/market-data/tick', symbolParam: 'symbol' }, V1TAIndexPrice: { topic: 'indexPrice', path: '/trading-api/v1/index-data', symbolParam: 'assetSymbol' } }; function getBullishSubscriptionTarget(channel) { const target = BULLISH_SUBSCRIPTION_TARGETS[channel]; if (target === undefined) { throw new Error(`BullishRealTimeFeed unsupported channel ${channel}`); } return target; } export class BullishRealTimeFeed extends MultiConnectionRealTimeFeedBase { *_getRealTimeFeeds(exchange, filters, timeoutIntervalMS, onError) { for (const [path, pathFilters] of this.groupByPath(filters)) { yield new BullishSingleConnectionRealTimeFeed(exchange, path, pathFilters, timeoutIntervalMS, onError); } } groupByPath(filters) { const filtersByPath = new Map(); for (const filter of filters) { const target = getBullishSubscriptionTarget(filter.channel); const pathFilters = filtersByPath.get(target.path) ?? []; pathFilters.push(filter); filtersByPath.set(target.path, pathFilters); } return filtersByPath; } } export class BullishSingleConnectionRealTimeFeed extends RealTimeFeedBase { path; wssURL = 'wss://api.exchange.bullish.com'; nextMessageId = 1; constructor(exchange, path, filters, timeoutIntervalMS, onError) { super(exchange, filters, timeoutIntervalMS, onError); this.path = path; } async getWebSocketUrl() { const baseURL = await super.getWebSocketUrl(); return `${baseURL.replace(/\/$/, '')}${this.path}`; } mapToSubscribeMessages(filters) { return filters.flatMap((filter) => { const target = getBullishSubscriptionTarget(filter.channel); if (target.symbolParam == null) { return [ { jsonrpc: '2.0', type: 'command', method: 'subscribe', id: (this.nextMessageId++).toString(), params: { topic: target.topic } } ]; } if (!filter.symbols || filter.symbols.length === 0) { throw new Error('BullishRealTimeFeed requires explicitly specified symbols when subscribing to live feed'); } return filter.symbols.map((symbol) => { return { jsonrpc: '2.0', type: 'command', method: 'subscribe', id: (this.nextMessageId++).toString(), params: { topic: target.topic, [target.symbolParam]: symbol } }; }); }); } messageIsError(message) { return message.error !== undefined && message.error !== null; } sendCustomPing = () => { this.send({ jsonrpc: '2.0', type: 'command', method: 'keepalivePing', id: (this.nextMessageId++).toString() }); }; messageIsHeartbeat(message) { return message.dataType === 'V1TAHeartbeat' || message.result?.message === 'Keep alive pong'; } } //# sourceMappingURL=bullish.js.map