UNPKG

tardis-dev

Version:

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

230 lines 8.7 kB
import { upperCaseSymbols } from "../handy.js"; import { PendingTickerInfoHelper } from "./mapper.js"; export const wooxTradesMapper = { canHandle(message) { return message.topic !== undefined && message.topic.endsWith('@trade'); }, getFilters(symbols) { symbols = upperCaseSymbols(symbols); return [ { channel: 'trade', symbols } ]; }, *map(message, localTimestamp) { const timestamp = new Date(message.ts); // any trade with source = 0 is mainly for informational purposes for our users, not actual trades printed on WOO X if (message.data.source === 0) { return; } yield { type: 'trade', symbol: message.data.symbol, exchange: 'woo-x', id: undefined, price: message.data.price, amount: message.data.size, side: message.data.side === 'SELL' ? 'sell' : 'buy', timestamp, localTimestamp: localTimestamp }; } }; export class WooxBookChangeMapper { _symbolToDepthInfoMapping = {}; canHandle(message) { if ('id' in message) { return message.id.endsWith('@orderbook'); } if ('topic' in message) { return message.topic.endsWith('@orderbookupdate'); } return false; } getFilters(symbols) { symbols = upperCaseSymbols(symbols); return [ { channel: 'orderbook', symbols }, { channel: 'orderbookupdate', symbols } ]; } *map(message, localTimestamp) { const symbol = message.data.symbol; if (this._symbolToDepthInfoMapping[symbol] === undefined) { this._symbolToDepthInfoMapping[symbol] = { bufferedUpdates: [] }; } const symbolDepthInfo = this._symbolToDepthInfoMapping[symbol]; const snapshotAlreadyProcessed = symbolDepthInfo.snapshotProcessed; // first check if received message is snapshot and process it as such if it is if ('id' in message && message.success) { yield { type: 'book_change', symbol, exchange: 'woo-x', isSnapshot: true, bids: message.data.bids.map(this._mapBookLevel), asks: message.data.asks.map(this._mapBookLevel), timestamp: new Date(message.data.ts), localTimestamp }; // mark given symbol depth info that has snapshot processed symbolDepthInfo.lastUpdateTimestamp = message.data.ts; symbolDepthInfo.snapshotProcessed = true; // if there were any depth updates buffered, let's proccess those for (const update of symbolDepthInfo.bufferedUpdates) { const bookChange = this._mapBookDepthUpdate(update, localTimestamp, symbolDepthInfo, symbol); if (bookChange !== undefined) { yield bookChange; } } // remove all buffered updates symbolDepthInfo.bufferedUpdates = []; } else if (snapshotAlreadyProcessed) { // snapshot was already processed let's map the message as normal book_change const bookChange = this._mapBookDepthUpdate(message, localTimestamp, symbolDepthInfo, symbol); if (bookChange !== undefined) { yield bookChange; } } else { // if snapshot hasn't been yet processed and we've got depthUpdate message, let's buffer it for later processing symbolDepthInfo.bufferedUpdates.push(message); } } _mapBookDepthUpdate(wooxBookUpdate, localTimestamp, depthInfo, symbol) { if (wooxBookUpdate.data.prevTs < depthInfo.lastUpdateTimestamp) { return; } return { type: 'book_change', symbol, exchange: 'woo-x', isSnapshot: false, bids: wooxBookUpdate.data.bids.map(this._mapBookLevel), asks: wooxBookUpdate.data.asks.map(this._mapBookLevel), timestamp: new Date(wooxBookUpdate.ts), localTimestamp }; } _mapBookLevel(level) { const price = level[0]; const amount = level[1]; return { price, amount }; } } export class WooxDerivativeTickerMapper { pendingTickerInfoHelper = new PendingTickerInfoHelper(); _indexPrices = new Map(); canHandle(message) { if (message.topic === undefined) { return false; } const symbol = (message.data && message.data.symbol) || ''; const isPerp = symbol.startsWith('PERP_'); return ((message.topic.endsWith('@trade') && isPerp) || (message.topic.endsWith('@markprice') && isPerp) || (message.topic.endsWith('@estfundingrate') && isPerp) || message.topic.endsWith('@indexprice') || (message.topic.endsWith('@openinterest') && isPerp)); } getFilters(symbols) { symbols = upperCaseSymbols(symbols); const spotSymbols = symbols !== undefined ? symbols.map((s) => s.replace('PERP_', 'SPOT_')) : []; return [ { channel: 'trade', symbols }, { channel: 'markprice', symbols }, { channel: 'estfundingrate', symbols }, { channel: 'openinterest', symbols }, { channel: 'indexprice', symbols: spotSymbols } ]; } *map(message, localTimestamp) { if (message.topic.endsWith('@indexprice')) { this._indexPrices.set(message.data.symbol.replace('SPOT_', 'PERP_'), message.data.price); } else { const symbol = message.data.symbol; const pendingTickerInfo = this.pendingTickerInfoHelper.getPendingTickerInfo(symbol, 'woo-x'); const lastIndexPrice = this._indexPrices.get(symbol); if (lastIndexPrice !== undefined) { pendingTickerInfo.updateIndexPrice(lastIndexPrice); } if (message.topic.endsWith('@markprice')) { pendingTickerInfo.updateMarkPrice(message.data.price); pendingTickerInfo.updateTimestamp(new Date(message.ts)); } if (message.topic.endsWith('@trade')) { pendingTickerInfo.updateLastPrice(message.data.price); pendingTickerInfo.updateTimestamp(new Date(message.ts)); } if (message.topic.endsWith('@estfundingrate')) { pendingTickerInfo.updateFundingRate(message.data.fundingRate); pendingTickerInfo.updateFundingTimestamp(new Date(message.data.fundingTs)); pendingTickerInfo.updateTimestamp(new Date(message.ts)); } if (message.topic.endsWith('@openinterest')) { pendingTickerInfo.updateOpenInterest(message.data.openInterest); pendingTickerInfo.updateTimestamp(new Date(message.ts)); } if (pendingTickerInfo.hasChanged()) { yield pendingTickerInfo.getSnapshot(localTimestamp); } } } } export class WooxBookTickerMapper { canHandle(message) { return message.topic !== undefined && message.topic.endsWith('@bbo'); } getFilters(symbols) { symbols = upperCaseSymbols(symbols); return [ { channel: 'bbo', symbols } ]; } *map(wooxBBOMessage, localTimestamp) { const wooxBookTicker = wooxBBOMessage.data; const ticker = { type: 'book_ticker', symbol: wooxBookTicker.symbol, exchange: 'woo-x', askAmount: wooxBookTicker.askSize !== undefined ? wooxBookTicker.askSize : undefined, askPrice: wooxBookTicker.ask !== undefined ? wooxBookTicker.ask : undefined, bidPrice: wooxBookTicker.bid !== undefined ? wooxBookTicker.bid : undefined, bidAmount: wooxBookTicker.bidSize !== undefined ? wooxBookTicker.bidSize : undefined, timestamp: new Date(wooxBBOMessage.ts), localTimestamp: localTimestamp }; yield ticker; } } //# sourceMappingURL=woox.js.map