@hackape/tardis-dev
Version:
Convenient access to tick-level historical and real-time cryptocurrency market data via Node.js
118 lines (100 loc) • 3.11 kB
text/typescript
import { BookChange, Exchange, Trade } from '../types'
import { Mapper } from './mapper'
// https://www.gate.io/docs/websocket/index.html
export class GateIOTradesMapper implements Mapper<'gate-io', Trade> {
private readonly _seenSymbols = new Set<string>()
constructor(private readonly _exchange: Exchange) {}
canHandle(message: any) {
return message.method === 'trades.update'
}
getFilters(symbols?: string[]) {
return [
{
channel: 'trades',
symbols
}
]
}
*map(tradesMessage: GateIOTrades, localTimestamp: Date): IterableIterator<Trade> {
const symbol = tradesMessage.params[0]
// gate io sends trades from newest to oldest for some reason
for (const gateIOTrade of tradesMessage.params[1].reverse()) {
// always ignore first returned trade as it's a 'stale' trade, which has already been published before disconnect
if (this._seenSymbols.has(symbol) === false) {
this._seenSymbols.add(symbol)
break
}
const timestamp = new Date(gateIOTrade.time * 1000)
timestamp.μs = Math.floor(gateIOTrade.time * 1000000) % 1000
yield {
type: 'trade',
symbol,
exchange: this._exchange,
id: gateIOTrade.id.toString(),
price: Number(gateIOTrade.price),
amount: Number(gateIOTrade.amount),
side: gateIOTrade.type == 'sell' ? 'sell' : 'buy',
timestamp,
localTimestamp: localTimestamp
}
}
}
}
const mapBookLevel = (level: GateIODepthLevel) => {
const price = Number(level[0])
const amount = Number(level[1])
return { price, amount }
}
export class GateIOBookChangeMapper implements Mapper<'gate-io', BookChange> {
constructor(private readonly _exchange: Exchange) {}
canHandle(message: any) {
return message.method === 'depth.update'
}
getFilters(symbols?: string[]) {
return [
{
channel: 'depth',
symbols
}
]
}
*map(depthMessage: GateIODepth, localTimestamp: Date): IterableIterator<BookChange> {
const symbol = depthMessage.params[2]
const isSnapshot = depthMessage.params[0]
const bids = Array.isArray(depthMessage.params[1].bids) ? depthMessage.params[1].bids : []
const asks = Array.isArray(depthMessage.params[1].asks) ? depthMessage.params[1].asks : []
yield {
type: 'book_change',
symbol,
exchange: this._exchange,
isSnapshot,
bids: bids.map(mapBookLevel),
asks: asks.map(mapBookLevel),
timestamp: localTimestamp,
localTimestamp: localTimestamp
}
}
}
type GateIOTrade = {
id: number
time: number
price: string
amount: string
type: 'sell' | 'buy'
}
type GateIOTrades = {
method: 'trades.update'
params: [string, GateIOTrade[]]
}
type GateIODepthLevel = [string, string]
type GateIODepth = {
method: 'depth.update'
params: [
boolean,
{
bids?: GateIODepthLevel[]
asks?: GateIODepthLevel[]
},
string
]
}