UNPKG

tardis-machine

Version:

Locally runnable server with built-in data caching, providing both tick-level historical and consolidated real-time cryptocurrency market data via HTTP and WebSocket APIs

624 lines 18.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.subscriptionsMappers = void 0; // https://www.bitmex.com/app/wsAPI const bitmexMapper = { canHandle: (message) => { return message.op === 'subscribe'; }, map: (message) => { const args = typeof message.args === 'string' ? [message.args] : message.args; return args.map((arg) => { const channelSymbols = arg.split(':'); if (channelSymbols.length == 1) { return { channel: channelSymbols[0] }; } return { channel: channelSymbols[0], symbols: [channelSymbols[1]] }; }); } }; // https://docs.pro.coinbase.com/#protocol-overview const coinbaseMaper = { canHandle: (message) => { return message.type === 'subscribe'; }, map: (message) => { const topLevelSymbols = message.product_ids; const finalChannels = []; const channelMappings = { full: ['received', 'open', 'done', 'match', 'change', 'full_snapshot'], level2: ['snapshot', 'l2update'], matches: ['match', 'last_match'], ticker: ['ticker'] }; message.channels.forEach((channel) => { const channelName = typeof channel == 'string' ? channel : channel.name; const symbols = typeof channel == 'string' ? topLevelSymbols : channel.product_ids; const mappedChannels = channelMappings[channelName]; mappedChannels.forEach((channel) => { finalChannels.push({ channel, symbols }); }); }); return finalChannels; } }; // https://docs.deribit.com/v2/#subscription-management const deribitMapper = { canHandle: (message) => { return message.method === 'public/subscribe'; }, map: (message) => { return message.params.channels.map((channel) => { const lastSeparator = channel.lastIndexOf('.'); const firstSeparator = channel.indexOf('.'); return { channel: channel.slice(0, firstSeparator), // handle both // "deribit_price_ranking.btc_usd" and "book.ETH-PERPETUAL.100.1.100ms" cases // we need to extract channel name and symbols out of such strings symbols: [channel.slice(firstSeparator + 1, lastSeparator == firstSeparator ? undefined : lastSeparator)] }; }); } }; // https://www.cryptofacilities.com/resources/hc/en-us/sections/360000120914-Websocket-API-Public const cryptofacilitiesMapper = { canHandle: (message) => { return message.event == 'subscribe'; }, map: (message) => { return [ { channel: message.feed, symbols: message.product_ids } ]; } }; // https://www.bitstamp.net/websocket/v2/ const bitstampMapper = { canHandle: (message) => { return message.event == 'bts:subscribe'; }, map: (message) => { const separator = message.data.channel.lastIndexOf('_'); return [ { channel: message.data.channel.slice(0, separator), symbols: [message.data.channel.slice(separator + 1)] } ]; } }; // https://www.okex.com/docs/en/#spot_ws-sub const okexMapper = { canHandle: (message) => { return message.op == 'subscribe'; }, map: (message) => { return message.args.map((arg) => { const separator = arg.indexOf(':'); return { channel: arg.slice(0, separator), symbols: [arg.slice(separator + 1)] }; }); } }; // https://docs.ftx.com/#request-format const ftxMapper = { canHandle: (message) => { return message.op === 'subscribe'; }, map: (message) => { return [ { channel: message.channel, symbols: [message.market] } ]; } }; // https://www.kraken.com/features/websocket-api#message-subscribe const krakenMapper = { canHandle: (message) => { return message.event === 'subscribe'; }, map: (message) => { return [ { channel: message.subscription.name, symbols: message.pair } ]; } }; // https://lightning.bitflyer.com/docs?lang=en#json-rpc-2.0-over-websocket const bitflyerMapper = { canHandle: (message) => { return message.method === 'subscribe'; }, map: (message) => { const availableChannels = ['lightning_board_snapshot', 'lightning_board', 'lightning_ticker', 'lightning_executions']; const inputChannel = message.params.channel; const channel = availableChannels.find((c) => inputChannel.startsWith(c)); const symbol = inputChannel.slice(channel.length + 1); return [ { channel, symbols: [symbol] } ]; } }; // https://docs.gemini.com/websocket-api/#market-data-version-2 const geminiMapper = { canHandle: (message) => { return message.type === 'subscribe'; }, map: (message) => { const finalChannels = []; const channelMappings = { l2: ['trade', 'l2_updates', 'auction_open', 'auction_indicative', 'auction_result'] }; message.subscriptions.forEach((sub) => { const matchingChannels = channelMappings[sub.name]; matchingChannels.forEach((channel) => { finalChannels.push({ channel, symbols: sub.symbols }); }); }); return finalChannels; } }; // https://binance-docs.github.io/apidocs/futures/en/#live-subscribing-unsubscribing-to-streams const binanceMapper = { canHandle: (message) => { return message.method === 'SUBSCRIBE'; }, map: (message) => { return message.params.map((param) => { const lastSeparator = param.lastIndexOf('@'); const firstSeparator = param.indexOf('@'); return { channel: param.slice(firstSeparator + 1, lastSeparator == firstSeparator ? undefined : lastSeparator), symbols: [param.slice(0, firstSeparator)] }; }); } }; // https://docs.binance.org/api-reference/dex-api/ws-connection.html const binanceDEXMapper = { canHandle: (message) => { return message.method === 'subscribe'; }, map: (message) => { return [ { channel: message.topic, symbols: message.symbols } ]; } }; // https://huobiapi.github.io/docs/spot/v1/en/#websocket-market-data const huobiMapper = { canHandle: (message) => { return message.sub !== undefined; }, map: (message) => { const pieces = message.sub.split('.'); return [ { channel: pieces[2], symbols: [pieces[1]] } ]; } }; // https://github.com/bybit-exchange/bybit-official-api-docs/blob/master/en/websocket.md const bybitMapper = { canHandle: (message) => { return message.op === 'subscribe'; }, map: (message) => { return message.args.map((arg) => { const pieces = arg.split('.'); return { channel: pieces[0], symbols: [pieces[pieces.length - 1]] }; }); } }; const bybitSpotMapper = { canHandle: (message) => { return message.event === 'sub'; }, map: (message) => { return [ { channel: message.topic, symbols: [message.symbol] } ]; } }; const blockchainComMapper = { canHandle: (message) => { return message.action === 'subscribe'; }, map: (message) => { return [ { channel: message.channel, symbols: [message.symbol] } ]; } }; // https://api.hitbtc.com/#subscribe-to-trades const hitBtcMapper = { canHandle: (message) => { return message.method !== undefined; }, map: (message) => { const channelMappings = { subscribeTrades: ['snapshotTrades', 'updateTrades'], subscribeOrderbook: ['snapshotOrderbook', 'updateOrderbook'] }; return channelMappings[message.method].map((channel) => { return { channel, symbols: [message.params.symbol] }; }); } }; const bitfinexMapper = { canHandle: () => true, map: () => [] }; const coinflexMapper = { canHandle: (message) => { return message.op === 'subscribe'; }, map: (message) => { return message.args.map((arg) => { const split = arg.split(':'); return { channel: split[0], symbols: [split[1]] }; }); } }; const phemexMapper = { canHandle: (message) => { return message.method !== undefined; }, map: (message) => { const channelsMapping = { 'orderbook.subscribe': 'book', 'trade.subscribe': 'trades', 'market24h.subscribe': 'market24h' }; return [ { channel: channelsMapping[message.method], symbols: message.params } ]; } }; const deltaMapper = { canHandle: (message) => { return message.type === 'subscribe'; }, map: (message) => { return message.payload.channels.map((channel) => { return { channel: channel.name, symbols: channel.symbols !== undefined && channel.name === 'mark_price' ? channel.symbols.map((s) => `MARK:${s}`) : channel.symbols }; }); } }; const gateIOMapper = { canHandle: (message) => { return message.method !== undefined && message.method.endsWith('.subscribe'); }, map: (message) => { return [ { channel: message.method.split('.')[0], symbols: message.params.map((s) => { if (typeof s === 'string') { return s; } return s[0]; }) } ]; } }; const gateIOFuturesMapper = { canHandle: (message) => { return message.event === 'subscribe'; }, map: (message) => { return [ { channel: message.channel.split('.')[1], symbols: message.payload.map((s) => { if (typeof s === 'string') { return s; } return s[0]; }) } ]; } }; const poloniexMapper = { canHandle: (message) => { return message.command === 'subscribe'; }, map: (message) => { return [ { channel: 'price_aggregated_book', symbols: [message.channel] } ]; } }; const ascendexMapper = { canHandle: (message) => { return message.op === 'sub' || message.op === 'req'; }, map: (message) => { const channel = message.action || message.ch.split(':')[0]; const symbol = (message.args && message.args.symbol) || message.ch.split(':')[1]; return [ { channel, symbols: symbol ? [symbol] : [] } ]; } }; const dydxMapper = { canHandle: (message) => { return message.type === 'subscribe'; }, map: (message) => { return [ { channel: message.channel, symbols: message.id ? [message.id] : [] } ]; } }; const upbitMapper = { canHandle: (message) => { return Array.isArray(message); }, map: (message) => { return message .filter((m) => { return m.type !== undefined; }) .map((m) => { return { channel: m.type, symbols: m.codes }; }); } }; const serumMaper = { canHandle: (message) => { return message.op === 'subscribe'; }, map: (message) => { const finalChannels = []; const channelMappings = { trades: ['recent_trades', 'trade'], level1: ['quote'], level2: ['l2snapshot', 'l2update'], level3: ['l3snapshot', 'open', 'fill', 'change', 'done'] }; const symbols = message.markets; const mappedChannels = channelMappings[message.channel]; mappedChannels.forEach((channel) => { finalChannels.push({ channel, symbols }); }); return finalChannels; } }; const cryptoComMapper = { canHandle: (message) => { return message.method === 'subscribe'; }, map: (message) => { return message.params.channels.map((channel) => { const parts = channel.split('.'); return { channel: parts[1], symbols: [parts[0]] }; }); } }; const kucoinMapper = { canHandle: (message) => { return message.type === 'subscribe'; }, map: (message) => { // "topic": "/market/ticker:BTC-USDT,ETH-USDT", const parts = message.topic.split(':'); const symbols = parts[1].split(','); return [ { channel: parts[0].substring(1), symbols } ]; } }; const bitnomialMapper = { canHandle: (message) => { return message.type === 'subscribe'; }, map: (message) => { const topLevelSymbols = message.product_codes; const finalChannels = []; const channelMappings = { book: ['book', 'levels'], trade: ['trade'], block: ['block'] }; message.channels.forEach((channel) => { const channelName = typeof channel == 'string' ? channel : channel.name; const symbols = typeof channel == 'string' ? topLevelSymbols : channel.product_codes; const mappedChannels = channelMappings[channelName]; mappedChannels.forEach((channel) => { finalChannels.push({ channel, symbols }); }); }); return finalChannels; } }; const wooxMapper = { canHandle: (message) => { return message.event === 'subscribe'; }, map: (message) => { const [symbol, channel] = message.topic.split('@'); return [ { channel, symbols: symbol } ]; } }; const bitgetMapper = { canHandle: (message) => { return message.op === 'subscribe'; }, map: (message) => { return message.args.map((arg) => { return { channel: arg.channel, symbols: [arg.instId] }; }); } }; const coinbaseInternationalMapper = { canHandle: (message) => { return message.type === 'SUBSCRIBE'; }, map: (message) => { return message.channels.map((channel) => { return { channel, symbols: message.product_ids }; }); } }; const hyperliquidMapper = { canHandle: (message) => { return message.method === 'subscribe'; }, map: (message) => { return [ { channel: message.type, symbols: [message.coin] } ]; } }; exports.subscriptionsMappers = { bitmex: bitmexMapper, coinbase: coinbaseMaper, deribit: deribitMapper, cryptofacilities: cryptofacilitiesMapper, bitstamp: bitstampMapper, okex: okexMapper, 'okex-futures': okexMapper, 'okex-swap': okexMapper, 'okex-options': okexMapper, ftx: ftxMapper, 'ftx-us': ftxMapper, kraken: krakenMapper, bitflyer: bitflyerMapper, gemini: geminiMapper, binance: binanceMapper, 'binance-futures': binanceMapper, 'binance-delivery': binanceMapper, 'binance-jersey': binanceMapper, 'binance-us': binanceMapper, 'binance-dex': binanceDEXMapper, huobi: huobiMapper, 'huobi-dm': huobiMapper, 'huobi-dm-swap': huobiMapper, 'huobi-dm-linear-swap': huobiMapper, bybit: bybitMapper, bitfinex: bitfinexMapper, 'bitfinex-derivatives': bitfinexMapper, okcoin: okexMapper, hitbtc: hitBtcMapper, coinflex: coinflexMapper, phemex: phemexMapper, delta: deltaMapper, 'gate-io': gateIOMapper, 'gate-io-futures': gateIOFuturesMapper, poloniex: poloniexMapper, ascendex: ascendexMapper, dydx: dydxMapper, 'dydx-v4': dydxMapper, 'huobi-dm-options': huobiMapper, 'binance-options': binanceMapper, upbit: upbitMapper, serum: serumMaper, 'star-atlas': serumMaper, mango: serumMaper, 'bybit-spot': bybitSpotMapper, 'crypto-com': cryptoComMapper, 'crypto-com-derivatives': cryptoComMapper, kucoin: kucoinMapper, bitnomial: bitnomialMapper, 'woo-x': wooxMapper, 'blockchain-com': blockchainComMapper, 'bybit-options': bybitMapper, 'binance-european-options': binanceMapper, 'okex-spreads': okexMapper, 'kucoin-futures': kucoinMapper, bitget: bitgetMapper, 'bitget-futures': bitgetMapper, 'coinbase-international': coinbaseInternationalMapper, hyperliquid: hyperliquidMapper }; //# sourceMappingURL=subscriptionsmappers.js.map