UNPKG

tardis-dev

Version:

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

208 lines 7.79 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CoinbaseInternationalDerivativeTickerMapper = exports.coinbaseInternationalBookTickerMapper = exports.CoinbaseInternationalBookChangMapper = exports.coinbaseInternationalTradesMapper = void 0; const handy_1 = require("../handy"); const mapper_1 = require("./mapper"); exports.coinbaseInternationalTradesMapper = { canHandle(message) { return message.channel === 'MATCH' && message.type === 'UPDATE'; }, getFilters(symbols) { symbols = (0, handy_1.upperCaseSymbols)(symbols); return [ { channel: 'MATCH', symbols } ]; }, *map(message, localTimestamp) { yield { type: 'trade', symbol: message.product_id, exchange: 'coinbase-international', id: message.match_id, price: Number(message.trade_price), amount: Number(message.trade_qty), side: message.aggressor_side === 'SELL' ? 'sell' : message.aggressor_side === 'BUY' ? 'buy' : 'unknown', timestamp: new Date(message.time), localTimestamp: localTimestamp }; } }; const mapUpdateBookLevel = (level) => { const price = Number(level[1]); const amount = Number(level[2]); return { price, amount }; }; const mapSnapshotBookLevel = (level) => { const price = Number(level[0]); const amount = Number(level[1]); return { price, amount }; }; const validAmountsOnly = (level) => { if (Number.isNaN(level.amount)) { return false; } if (level.amount < 0) { return false; } return true; }; class CoinbaseInternationalBookChangMapper { canHandle(message) { return message.channel === 'LEVEL2' && (message.type === 'SNAPSHOT' || message.type === 'UPDATE'); } getFilters(symbols) { symbols = (0, handy_1.upperCaseSymbols)(symbols); return [ { channel: 'LEVEL2', symbols } ]; } *map(message, localTimestamp) { if (message.type === 'SNAPSHOT') { let timestamp; if (message.time !== undefined) { timestamp = new Date(message.time); if (timestamp.valueOf() < 0) { timestamp = localTimestamp; } } else { timestamp = localTimestamp; } yield { type: 'book_change', symbol: message.product_id, exchange: 'coinbase-international', isSnapshot: true, bids: message.bids.map(mapSnapshotBookLevel).filter(validAmountsOnly), asks: message.asks.map(mapSnapshotBookLevel).filter(validAmountsOnly), timestamp, localTimestamp }; } else { let timestamp = new Date(message.time); yield { type: 'book_change', symbol: message.product_id, exchange: 'coinbase-international', isSnapshot: false, bids: message.changes.filter((c) => c[0] === 'BUY').map(mapUpdateBookLevel), asks: message.changes.filter((c) => c[0] === 'SELL').map(mapUpdateBookLevel), timestamp, localTimestamp: localTimestamp }; } } } exports.CoinbaseInternationalBookChangMapper = CoinbaseInternationalBookChangMapper; exports.coinbaseInternationalBookTickerMapper = { canHandle(message) { return message.channel === 'LEVEL1' && (message.type === 'SNAPSHOT' || message.type === 'UPDATE'); }, getFilters(symbols) { symbols = (0, handy_1.upperCaseSymbols)(symbols); return [ { channel: 'LEVEL1', symbols } ]; }, *map(message, localTimestamp) { let timestamp = new Date(message.time); if (message.time === undefined || timestamp.valueOf() < 0) { timestamp = localTimestamp; } yield { type: 'book_ticker', symbol: message.product_id, exchange: 'coinbase-international', askAmount: message.ask_qty !== undefined ? Number(message.ask_qty) : undefined, askPrice: message.ask_price !== undefined ? Number(message.ask_price) : undefined, bidPrice: message.bid_price !== undefined ? Number(message.bid_price) : undefined, bidAmount: message.bid_qty !== undefined ? Number(message.bid_qty) : undefined, timestamp, localTimestamp: localTimestamp }; } }; class CoinbaseInternationalDerivativeTickerMapper { constructor() { this.pendingTickerInfoHelper = new mapper_1.PendingTickerInfoHelper(); } canHandle(message) { // perps only if (message.product_id === undefined || message.product_id.endsWith('-PERP') === false) { return false; } if (message.channel === 'MATCH' && message.type === 'UPDATE') { return true; } if (message.channel === 'FUNDING' && message.type === 'UPDATE') { return true; } if (message.channel === 'RISK') { return true; } return false; } getFilters(symbols) { symbols = (0, handy_1.upperCaseSymbols)(symbols); return [ { channel: 'MATCH', symbols }, { channel: 'RISK', symbols }, { channel: 'FUNDING', symbols } ]; } *map(message, localTimestamp) { if (message.channel === 'MATCH') { const pendingTickerInfo = this.pendingTickerInfoHelper.getPendingTickerInfo(message.product_id, 'coinbase-international'); pendingTickerInfo.updateLastPrice(Number(message.trade_price)); return; } const pendingTickerInfo = this.pendingTickerInfoHelper.getPendingTickerInfo(message.product_id, 'coinbase-international'); if (message.channel === 'RISK') { if (message.index_price !== undefined) { pendingTickerInfo.updateIndexPrice(Number(message.index_price)); } if (message.mark_price !== undefined) { pendingTickerInfo.updateMarkPrice(Number(message.mark_price)); } if (message.open_interest !== undefined) { pendingTickerInfo.updateOpenInterest(Number(message.open_interest)); } } if (message.channel === 'FUNDING') { let nextFundingTime = new Date(message.time); if (message.is_final === false) { // If the field is_final is false, the message indicates the predicted funding rate for the next funding interval. // https://docs.cdp.coinbase.com/intx/docs/websocket-channels#funding-channel nextFundingTime.setUTCMinutes(0, 0, 0); nextFundingTime = (0, handy_1.addMinutes)(nextFundingTime, 60); pendingTickerInfo.updateFundingTimestamp(nextFundingTime); } pendingTickerInfo.updateFundingRate(Number(message.funding_rate)); } pendingTickerInfo.updateTimestamp(new Date(message.time)); if (pendingTickerInfo.hasChanged()) { yield pendingTickerInfo.getSnapshot(localTimestamp); } } } exports.CoinbaseInternationalDerivativeTickerMapper = CoinbaseInternationalDerivativeTickerMapper; //# sourceMappingURL=coinbaseinternational.js.map