tardis-dev
Version:
Convenient access to tick-level historical and real-time cryptocurrency market data via Node.js
161 lines • 5.67 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.coinbaseBookTickerMapper = exports.CoinbaseBookChangMapper = exports.coinbaseTradesMapper = void 0;
const handy_1 = require("../handy");
// https://docs.pro.coinbase.com/#websocket-feed
exports.coinbaseTradesMapper = {
canHandle(message) {
return message.type === 'match';
},
getFilters(symbols) {
symbols = (0, handy_1.upperCaseSymbols)(symbols);
return [
{
channel: 'match',
symbols
}
];
},
*map(message, localTimestamp) {
const timestamp = new Date(message.time);
timestamp.μs = (0, handy_1.parseμs)(message.time);
yield {
type: 'trade',
symbol: message.product_id,
exchange: 'coinbase',
id: String(message.trade_id),
price: Number(message.price),
amount: Number(message.size),
side: message.side === 'sell' ? 'buy' : 'sell', // coinbase side field indicates the maker order side
timestamp,
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 CoinbaseBookChangMapper {
_symbolLastTimestampMap = new Map();
canHandle(message) {
return message.type === 'l2update' || message.type === 'snapshot';
}
getFilters(symbols) {
symbols = (0, handy_1.upperCaseSymbols)(symbols);
return [
{
channel: 'snapshot',
symbols
},
{
channel: 'l2update',
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.μs = (0, handy_1.parseμs)(message.time);
}
}
else {
timestamp = localTimestamp;
}
yield {
type: 'book_change',
symbol: message.product_id,
exchange: 'coinbase',
isSnapshot: true,
bids: message.bids.map(mapSnapshotBookLevel).filter(validAmountsOnly),
asks: message.asks.map(mapSnapshotBookLevel).filter(validAmountsOnly),
timestamp,
localTimestamp
};
}
else {
// in very rare cases, Coinbase was returning timestamps that aren't valid, like: "time":"0001-01-01T00:00:00.000000Z"
// but l2update message was still valid and we need to process it, in such case use timestamp of previous message
let timestamp = new Date(message.time);
if (timestamp.valueOf() < 0) {
let previousValidTimestamp = this._symbolLastTimestampMap.get(message.product_id);
if (previousValidTimestamp === undefined) {
return;
}
timestamp = previousValidTimestamp;
}
else {
timestamp.μs = (0, handy_1.parseμs)(message.time);
this._symbolLastTimestampMap.set(message.product_id, timestamp);
}
yield {
type: 'book_change',
symbol: message.product_id,
exchange: 'coinbase',
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.CoinbaseBookChangMapper = CoinbaseBookChangMapper;
exports.coinbaseBookTickerMapper = {
canHandle(message) {
return message.type === 'ticker';
},
getFilters(symbols) {
symbols = (0, handy_1.upperCaseSymbols)(symbols);
return [
{
channel: 'ticker',
symbols
}
];
},
*map(message, localTimestamp) {
let timestamp = new Date(message.time);
if (message.time === undefined || timestamp.valueOf() < 0) {
timestamp = localTimestamp;
}
else {
timestamp.μs = (0, handy_1.parseμs)(message.time);
}
yield {
type: 'book_ticker',
symbol: message.product_id,
exchange: 'coinbase',
askAmount: message.best_ask_size !== undefined ? Number(message.best_ask_size) : undefined,
askPrice: message.best_ask !== undefined ? Number(message.best_ask) : undefined,
bidPrice: message.best_bid !== undefined ? Number(message.best_bid) : undefined,
bidAmount: message.best_bid_size !== undefined ? Number(message.best_bid_size) : undefined,
timestamp,
localTimestamp: localTimestamp
};
}
};
//# sourceMappingURL=coinbase.js.map