tardis-dev
Version:
Convenient access to tick-level historical and real-time cryptocurrency market data via Node.js
208 lines • 7.79 kB
JavaScript
;
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