tardis-dev 16.2.0 → 16.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/computable/computable.js.map +1 -1
- package/dist/consts.js +2 -2
- package/dist/consts.js.map +1 -1
- package/dist/handy.d.ts.map +1 -1
- package/dist/handy.js +1 -1
- package/dist/handy.js.map +1 -1
- package/dist/instrumentinfo.js +1 -1
- package/dist/instrumentinfo.js.map +1 -1
- package/dist/mappers/binance.d.ts.map +1 -1
- package/dist/mappers/binance.js.map +1 -1
- package/dist/mappers/bitget.d.ts +148 -1
- package/dist/mappers/bitget.d.ts.map +1 -1
- package/dist/mappers/bitget.js +160 -1
- package/dist/mappers/bitget.js.map +1 -1
- package/dist/mappers/bybit.d.ts.map +1 -1
- package/dist/mappers/bybit.js.map +1 -1
- package/dist/mappers/gateio.d.ts.map +1 -1
- package/dist/mappers/gateio.js.map +1 -1
- package/dist/mappers/gateiofutures.js.map +1 -1
- package/dist/mappers/huobi.d.ts.map +1 -1
- package/dist/mappers/huobi.js.map +1 -1
- package/dist/mappers/index.d.ts +9 -8
- package/dist/mappers/index.d.ts.map +1 -1
- package/dist/mappers/index.js +18 -9
- package/dist/mappers/index.js.map +1 -1
- package/dist/mappers/kucoin.d.ts.map +1 -1
- package/dist/mappers/kucoin.js.map +1 -1
- package/dist/mappers/okex.d.ts.map +1 -1
- package/dist/mappers/okex.js.map +1 -1
- package/dist/mappers/phemex.d.ts.map +1 -1
- package/dist/mappers/phemex.js +11 -2
- package/dist/mappers/phemex.js.map +1 -1
- package/dist/realtimefeeds/bitget.d.ts +4 -2
- package/dist/realtimefeeds/bitget.d.ts.map +1 -1
- package/dist/realtimefeeds/bitget.js +21 -7
- package/dist/realtimefeeds/bitget.js.map +1 -1
- package/dist/realtimefeeds/bitnomial.d.ts.map +1 -1
- package/dist/realtimefeeds/bitnomial.js.map +1 -1
- package/dist/realtimefeeds/coinbase.d.ts.map +1 -1
- package/dist/realtimefeeds/coinbase.js.map +1 -1
- package/dist/realtimefeeds/hitbtc.d.ts.map +1 -1
- package/dist/realtimefeeds/hitbtc.js.map +1 -1
- package/dist/realtimefeeds/huobi.d.ts.map +1 -1
- package/dist/realtimefeeds/huobi.js.map +1 -1
- package/dist/realtimefeeds/kucoinfutures.d.ts.map +1 -1
- package/dist/realtimefeeds/kucoinfutures.js.map +1 -1
- package/dist/realtimefeeds/realtimefeed.d.ts.map +1 -1
- package/dist/realtimefeeds/realtimefeed.js.map +1 -1
- package/dist/realtimefeeds/serum.d.ts.map +1 -1
- package/dist/realtimefeeds/serum.js.map +1 -1
- package/dist/replay.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/computable/computable.ts +14 -11
- package/src/consts.ts +2 -2
- package/src/handy.ts +30 -19
- package/src/instrumentinfo.ts +1 -1
- package/src/mappers/binance.ts +16 -8
- package/src/mappers/bitget.ts +237 -2
- package/src/mappers/bybit.ts +21 -16
- package/src/mappers/gateio.ts +4 -1
- package/src/mappers/gateiofutures.ts +2 -2
- package/src/mappers/huobi.ts +8 -6
- package/src/mappers/index.ts +39 -11
- package/src/mappers/kucoin.ts +4 -1
- package/src/mappers/okex.ts +24 -6
- package/src/mappers/phemex.ts +14 -4
- package/src/realtimefeeds/bitget.ts +24 -7
- package/src/realtimefeeds/bitnomial.ts +14 -11
- package/src/realtimefeeds/coinbase.ts +14 -11
- package/src/realtimefeeds/hitbtc.ts +10 -7
- package/src/realtimefeeds/huobi.ts +10 -2
- package/src/realtimefeeds/kucoinfutures.ts +4 -1
- package/src/realtimefeeds/realtimefeed.ts +5 -1
- package/src/realtimefeeds/serum.ts +14 -11
- package/src/replay.ts +2 -2
- package/src/types.ts +1 -1
package/src/mappers/binance.ts
CHANGED
|
@@ -5,9 +5,10 @@ import { Mapper, PendingTickerInfoHelper } from './mapper.ts'
|
|
|
5
5
|
|
|
6
6
|
// https://github.com/binance-exchange/binance-official-api-docs/blob/master/web-socket-streams.md
|
|
7
7
|
|
|
8
|
-
export class BinanceTradesMapper
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
export class BinanceTradesMapper implements Mapper<
|
|
9
|
+
'binance' | 'binance-jersey' | 'binance-us' | 'binance-futures' | 'binance-delivery',
|
|
10
|
+
Trade
|
|
11
|
+
> {
|
|
11
12
|
constructor(private readonly _exchange: Exchange) {}
|
|
12
13
|
|
|
13
14
|
canHandle(message: BinanceResponse<any>) {
|
|
@@ -53,14 +54,18 @@ export class BinanceTradesMapper
|
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
56
|
|
|
56
|
-
export class BinanceBookChangeMapper
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
export class BinanceBookChangeMapper implements Mapper<
|
|
58
|
+
'binance' | 'binance-jersey' | 'binance-us' | 'binance-futures' | 'binance-delivery',
|
|
59
|
+
BookChange
|
|
60
|
+
> {
|
|
59
61
|
protected readonly symbolToDepthInfoMapping: {
|
|
60
62
|
[key: string]: LocalDepthInfo
|
|
61
63
|
} = {}
|
|
62
64
|
|
|
63
|
-
constructor(
|
|
65
|
+
constructor(
|
|
66
|
+
protected readonly exchange: Exchange,
|
|
67
|
+
protected readonly ignoreBookSnapshotOverlapError: boolean
|
|
68
|
+
) {}
|
|
64
69
|
|
|
65
70
|
canHandle(message: BinanceResponse<any>) {
|
|
66
71
|
if (message.stream === undefined) {
|
|
@@ -217,7 +222,10 @@ export class BinanceFuturesBookChangeMapper
|
|
|
217
222
|
extends BinanceBookChangeMapper
|
|
218
223
|
implements Mapper<'binance-futures' | 'binance-delivery', BookChange>
|
|
219
224
|
{
|
|
220
|
-
constructor(
|
|
225
|
+
constructor(
|
|
226
|
+
protected readonly exchange: Exchange,
|
|
227
|
+
protected readonly ignoreBookSnapshotOverlapError: boolean
|
|
228
|
+
) {
|
|
221
229
|
super(exchange, ignoreBookSnapshotOverlapError)
|
|
222
230
|
}
|
|
223
231
|
|
package/src/mappers/bitget.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { upperCaseSymbols } from '../handy.ts'
|
|
2
|
-
import { BookChange, BookTicker, DerivativeTicker, Exchange, Trade } from '../types.ts'
|
|
1
|
+
import { asNumberIfValid, upperCaseSymbols } from '../handy.ts'
|
|
2
|
+
import { BookChange, BookTicker, DerivativeTicker, Exchange, Liquidation, Trade } from '../types.ts'
|
|
3
3
|
import { Mapper, PendingTickerInfoHelper } from './mapper.ts'
|
|
4
4
|
|
|
5
5
|
export class BitgetTradesMapper implements Mapper<'bitget' | 'bitget-futures', Trade> {
|
|
@@ -155,6 +155,182 @@ export class BitgetDerivativeTickerMapper implements Mapper<'bitget-futures', De
|
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
+
export class BitgetV3TradesMapper implements Mapper<'bitget' | 'bitget-futures', Trade> {
|
|
159
|
+
constructor(private readonly _exchange: Exchange) {}
|
|
160
|
+
|
|
161
|
+
canHandle(message: BitgetV3TradeMessage) {
|
|
162
|
+
return message.arg.topic === 'publicTrade' && message.action === 'update'
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
getFilters(symbols?: string[]) {
|
|
166
|
+
symbols = upperCaseSymbols(symbols)
|
|
167
|
+
|
|
168
|
+
return [
|
|
169
|
+
{
|
|
170
|
+
channel: 'publicTrade',
|
|
171
|
+
symbols
|
|
172
|
+
} as const
|
|
173
|
+
]
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
*map(message: BitgetV3TradeMessage, localTimestamp: Date): IterableIterator<Trade> {
|
|
177
|
+
for (const trade of message.data) {
|
|
178
|
+
yield {
|
|
179
|
+
type: 'trade',
|
|
180
|
+
symbol: message.arg.symbol,
|
|
181
|
+
exchange: this._exchange,
|
|
182
|
+
id: trade.i,
|
|
183
|
+
price: Number(trade.p),
|
|
184
|
+
amount: Number(trade.v),
|
|
185
|
+
side: trade.S === 'buy' ? 'buy' : 'sell',
|
|
186
|
+
timestamp: new Date(Number(trade.T)),
|
|
187
|
+
localTimestamp
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export class BitgetV3BookChangeMapper implements Mapper<'bitget' | 'bitget-futures', BookChange> {
|
|
194
|
+
constructor(private readonly _exchange: Exchange) {}
|
|
195
|
+
|
|
196
|
+
canHandle(message: BitgetV3OrderbookMessage) {
|
|
197
|
+
return message.arg.topic === 'books' && (message.action === 'snapshot' || message.action === 'update')
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
getFilters(symbols?: string[]) {
|
|
201
|
+
symbols = upperCaseSymbols(symbols)
|
|
202
|
+
|
|
203
|
+
return [
|
|
204
|
+
{
|
|
205
|
+
channel: 'books',
|
|
206
|
+
symbols
|
|
207
|
+
} as const
|
|
208
|
+
]
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
*map(message: BitgetV3OrderbookMessage, localTimestamp: Date): IterableIterator<BookChange> {
|
|
212
|
+
for (const orderbookData of message.data) {
|
|
213
|
+
yield {
|
|
214
|
+
type: 'book_change',
|
|
215
|
+
symbol: message.arg.symbol,
|
|
216
|
+
exchange: this._exchange,
|
|
217
|
+
isSnapshot: message.action === 'snapshot',
|
|
218
|
+
bids: orderbookData.b.map(mapPriceLevel),
|
|
219
|
+
asks: orderbookData.a.map(mapPriceLevel),
|
|
220
|
+
timestamp: new Date(Number(orderbookData.ts)),
|
|
221
|
+
localTimestamp
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export class BitgetV3BookTickerMapper implements Mapper<'bitget' | 'bitget-futures', BookTicker> {
|
|
228
|
+
constructor(private readonly _exchange: Exchange) {}
|
|
229
|
+
|
|
230
|
+
canHandle(message: BitgetV3BBoMessage) {
|
|
231
|
+
return message.arg.topic === 'books1' && message.action === 'snapshot'
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
getFilters(symbols?: string[]) {
|
|
235
|
+
symbols = upperCaseSymbols(symbols)
|
|
236
|
+
|
|
237
|
+
return [
|
|
238
|
+
{
|
|
239
|
+
channel: 'books1',
|
|
240
|
+
symbols
|
|
241
|
+
} as const
|
|
242
|
+
]
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
*map(message: BitgetV3BBoMessage, localTimestamp: Date): IterableIterator<BookTicker> {
|
|
246
|
+
for (const bboMessage of message.data) {
|
|
247
|
+
yield {
|
|
248
|
+
type: 'book_ticker',
|
|
249
|
+
symbol: message.arg.symbol,
|
|
250
|
+
exchange: this._exchange,
|
|
251
|
+
askAmount: bboMessage.a[0] ? asNumberIfValid(bboMessage.a[0][1]) : undefined,
|
|
252
|
+
askPrice: bboMessage.a[0] ? asNumberIfValid(bboMessage.a[0][0]) : undefined,
|
|
253
|
+
bidPrice: bboMessage.b[0] ? asNumberIfValid(bboMessage.b[0][0]) : undefined,
|
|
254
|
+
bidAmount: bboMessage.b[0] ? asNumberIfValid(bboMessage.b[0][1]) : undefined,
|
|
255
|
+
timestamp: new Date(Number(bboMessage.ts)),
|
|
256
|
+
localTimestamp
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export class BitgetV3DerivativeTickerMapper implements Mapper<'bitget-futures', DerivativeTicker> {
|
|
263
|
+
private readonly pendingTickerInfoHelper = new PendingTickerInfoHelper()
|
|
264
|
+
|
|
265
|
+
canHandle(message: BitgetV3TickerMessage) {
|
|
266
|
+
return message.arg.topic === 'ticker' && (message.action === 'snapshot' || message.action === 'update')
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
getFilters(symbols?: string[]) {
|
|
270
|
+
symbols = upperCaseSymbols(symbols)
|
|
271
|
+
|
|
272
|
+
return [
|
|
273
|
+
{
|
|
274
|
+
channel: 'ticker',
|
|
275
|
+
symbols
|
|
276
|
+
} as const
|
|
277
|
+
]
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
*map(message: BitgetV3TickerMessage, localTimestamp: Date): IterableIterator<DerivativeTicker> {
|
|
281
|
+
for (const tickerMessage of message.data) {
|
|
282
|
+
const pendingTickerInfo = this.pendingTickerInfoHelper.getPendingTickerInfo(message.arg.symbol, 'bitget-futures')
|
|
283
|
+
|
|
284
|
+
pendingTickerInfo.updateIndexPrice(Number(tickerMessage.indexPrice))
|
|
285
|
+
pendingTickerInfo.updateMarkPrice(Number(tickerMessage.markPrice))
|
|
286
|
+
pendingTickerInfo.updateOpenInterest(Number(tickerMessage.openInterest))
|
|
287
|
+
pendingTickerInfo.updateLastPrice(Number(tickerMessage.lastPrice))
|
|
288
|
+
pendingTickerInfo.updateTimestamp(new Date(Number(message.ts)))
|
|
289
|
+
|
|
290
|
+
if (tickerMessage.nextFundingTime !== '' && tickerMessage.nextFundingTime !== '0') {
|
|
291
|
+
pendingTickerInfo.updateFundingTimestamp(new Date(Number(tickerMessage.nextFundingTime)))
|
|
292
|
+
pendingTickerInfo.updateFundingRate(Number(tickerMessage.fundingRate))
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (pendingTickerInfo.hasChanged()) {
|
|
296
|
+
yield pendingTickerInfo.getSnapshot(localTimestamp)
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export class BitgetV3LiquidationsMapper implements Mapper<'bitget-futures', Liquidation> {
|
|
303
|
+
canHandle(message: BitgetV3LiquidationMessage) {
|
|
304
|
+
return message.arg.topic === 'liquidation' && message.action === 'update'
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
getFilters() {
|
|
308
|
+
return [
|
|
309
|
+
{
|
|
310
|
+
channel: 'liquidation',
|
|
311
|
+
symbols: undefined
|
|
312
|
+
} as const
|
|
313
|
+
]
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
*map(message: BitgetV3LiquidationMessage, localTimestamp: Date): IterableIterator<Liquidation> {
|
|
317
|
+
for (const liquidation of message.data) {
|
|
318
|
+
yield {
|
|
319
|
+
type: 'liquidation',
|
|
320
|
+
symbol: liquidation.symbol,
|
|
321
|
+
exchange: 'bitget-futures',
|
|
322
|
+
id: undefined,
|
|
323
|
+
price: Number(liquidation.price),
|
|
324
|
+
amount: Number(liquidation.amount),
|
|
325
|
+
// Bitget side is position side, normalized side is the liquidated aggressor side.
|
|
326
|
+
side: liquidation.side === 'buy' ? 'sell' : 'buy',
|
|
327
|
+
timestamp: new Date(Number(liquidation.ts)),
|
|
328
|
+
localTimestamp
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
158
334
|
type BitgetTradeMessage = {
|
|
159
335
|
action: 'update'
|
|
160
336
|
arg: { instType: 'SPOT'; channel: 'trade'; instId: 'OPUSDT' }
|
|
@@ -214,3 +390,62 @@ type BitgetTickerMessage = {
|
|
|
214
390
|
]
|
|
215
391
|
ts: 1730332823220
|
|
216
392
|
}
|
|
393
|
+
|
|
394
|
+
type BitgetV3TradeMessage = {
|
|
395
|
+
action: 'snapshot' | 'update'
|
|
396
|
+
arg: { instType: string; topic: 'publicTrade'; symbol: string }
|
|
397
|
+
data: { i: string; p: string; v: string; S: 'buy' | 'sell'; T: string; L: string; isRPI?: string }[]
|
|
398
|
+
ts: number
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
type BitgetV3BookLevel = [string, string]
|
|
402
|
+
|
|
403
|
+
type BitgetV3OrderbookMessage = {
|
|
404
|
+
action: 'snapshot' | 'update'
|
|
405
|
+
arg: { instType: string; topic: 'books'; symbol: string }
|
|
406
|
+
data: { a: BitgetV3BookLevel[]; b: BitgetV3BookLevel[]; checksum: number; seq: number; pseq: number; ts: string }[]
|
|
407
|
+
ts: number
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
type BitgetV3BBoMessage = {
|
|
411
|
+
action: 'snapshot'
|
|
412
|
+
arg: { instType: string; topic: 'books1'; symbol: string }
|
|
413
|
+
data: { a: BitgetV3BookLevel[]; b: BitgetV3BookLevel[]; checksum: number; seq: number; pseq: number; ts: string }[]
|
|
414
|
+
ts: number
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
type BitgetV3TickerMessage = {
|
|
418
|
+
action: 'snapshot' | 'update'
|
|
419
|
+
arg: { instType: string; topic: 'ticker'; symbol: string }
|
|
420
|
+
data: [
|
|
421
|
+
{
|
|
422
|
+
highPrice24h: string
|
|
423
|
+
lowPrice24h: string
|
|
424
|
+
openPrice24h: string
|
|
425
|
+
lastPrice: string
|
|
426
|
+
turnover24h: string
|
|
427
|
+
volume24h: string
|
|
428
|
+
bid1Price: string
|
|
429
|
+
ask1Price: string
|
|
430
|
+
bid1Size: string
|
|
431
|
+
ask1Size: string
|
|
432
|
+
price24hPcnt: string
|
|
433
|
+
indexPrice: string
|
|
434
|
+
markPrice: string
|
|
435
|
+
fundingRate: string
|
|
436
|
+
openInterest: string
|
|
437
|
+
deliveryTime: string
|
|
438
|
+
deliveryStartTime: string
|
|
439
|
+
deliveryStatus: string
|
|
440
|
+
nextFundingTime: string
|
|
441
|
+
}
|
|
442
|
+
]
|
|
443
|
+
ts: number
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
type BitgetV3LiquidationMessage = {
|
|
447
|
+
action: 'update'
|
|
448
|
+
arg: { instType: string; topic: 'liquidation' }
|
|
449
|
+
data: { symbol: string; side: 'buy' | 'sell'; price: string; amount: string; ts: string }[]
|
|
450
|
+
ts: number
|
|
451
|
+
}
|
package/src/mappers/bybit.ts
CHANGED
|
@@ -44,7 +44,10 @@ export class BybitV5TradesMapper implements Mapper<'bybit' | 'bybit-spot' | 'byb
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
export class BybitV5BookChangeMapper implements Mapper<'bybit' | 'bybit-spot' | 'bybit-options', BookChange> {
|
|
47
|
-
constructor(
|
|
47
|
+
constructor(
|
|
48
|
+
protected readonly _exchange: Exchange,
|
|
49
|
+
private readonly _depth: number
|
|
50
|
+
) {}
|
|
48
51
|
|
|
49
52
|
canHandle(message: BybitV5OrderBookMessage) {
|
|
50
53
|
if (message.topic === undefined) {
|
|
@@ -388,8 +391,8 @@ export class BybitTradesMapper implements Mapper<'bybit', Trade> {
|
|
|
388
391
|
'trade_time_ms' in trade
|
|
389
392
|
? new Date(Number(trade.trade_time_ms))
|
|
390
393
|
: 'tradeTimeMs' in trade
|
|
391
|
-
|
|
392
|
-
|
|
394
|
+
? new Date(Number(trade.tradeTimeMs))
|
|
395
|
+
: new Date(trade.timestamp)
|
|
393
396
|
|
|
394
397
|
yield {
|
|
395
398
|
type: 'trade',
|
|
@@ -407,7 +410,10 @@ export class BybitTradesMapper implements Mapper<'bybit', Trade> {
|
|
|
407
410
|
}
|
|
408
411
|
|
|
409
412
|
export class BybitBookChangeMapper implements Mapper<'bybit', BookChange> {
|
|
410
|
-
constructor(
|
|
413
|
+
constructor(
|
|
414
|
+
protected readonly _exchange: Exchange,
|
|
415
|
+
private readonly _canUseBook200Channel: boolean
|
|
416
|
+
) {}
|
|
411
417
|
|
|
412
418
|
canHandle(message: BybitDataMessage) {
|
|
413
419
|
if (message.topic === undefined) {
|
|
@@ -449,8 +455,8 @@ export class BybitBookChangeMapper implements Mapper<'bybit', BookChange> {
|
|
|
449
455
|
? 'order_book' in message.data
|
|
450
456
|
? message.data.order_book
|
|
451
457
|
: 'orderBook' in message.data
|
|
452
|
-
|
|
453
|
-
|
|
458
|
+
? message.data.orderBook
|
|
459
|
+
: message.data
|
|
454
460
|
: [...message.data.delete, ...message.data.update, ...message.data.insert]
|
|
455
461
|
|
|
456
462
|
const timestampBybit = message.timestamp_e6 !== undefined ? Number(message.timestamp_e6) : Number(message.timestampE6)
|
|
@@ -858,16 +864,15 @@ type BybitInstrumentUpdate = {
|
|
|
858
864
|
ask1Price: '21213.50'
|
|
859
865
|
}
|
|
860
866
|
|
|
861
|
-
type BybitInstrumentDataMessage =
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
}
|
|
867
|
+
type BybitInstrumentDataMessage = BybitDataMessage & {
|
|
868
|
+
timestamp_e6: string
|
|
869
|
+
timestampE6: string
|
|
870
|
+
data:
|
|
871
|
+
| BybitInstrumentUpdate
|
|
872
|
+
| {
|
|
873
|
+
update: [BybitInstrumentUpdate]
|
|
874
|
+
}
|
|
875
|
+
}
|
|
871
876
|
|
|
872
877
|
type BybitLiquidationMessage = BybitDataMessage & {
|
|
873
878
|
generated: true
|
package/src/mappers/gateio.ts
CHANGED
|
@@ -60,7 +60,10 @@ export class GateIOV4BookChangeMapper implements Mapper<'gate-io', BookChange> {
|
|
|
60
60
|
[key: string]: LocalDepthInfo
|
|
61
61
|
} = {}
|
|
62
62
|
|
|
63
|
-
constructor(
|
|
63
|
+
constructor(
|
|
64
|
+
protected readonly exchange: Exchange,
|
|
65
|
+
protected readonly ignoreBookSnapshotOverlapError: boolean
|
|
66
|
+
) {}
|
|
64
67
|
|
|
65
68
|
canHandle(message: GateV4OrderBookUpdate | Gatev4OrderBookSnapshot) {
|
|
66
69
|
if (message.channel === undefined) {
|
|
@@ -76,8 +76,8 @@ export class GateIOFuturesBookChangeMapper implements Mapper<'gate-io-futures',
|
|
|
76
76
|
depthMessage.time_ms !== undefined
|
|
77
77
|
? new Date(depthMessage.time_ms)
|
|
78
78
|
: depthMessage.result.t !== undefined
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
? new Date(depthMessage.result.t)
|
|
80
|
+
: new Date(depthMessage.time * 1000)
|
|
81
81
|
|
|
82
82
|
// snapshot
|
|
83
83
|
yield {
|
package/src/mappers/huobi.ts
CHANGED
|
@@ -5,9 +5,10 @@ import { Mapper, PendingTickerInfoHelper } from './mapper.ts'
|
|
|
5
5
|
// https://huobiapi.github.io/docs/spot/v1/en/#websocket-market-data
|
|
6
6
|
// https://github.com/huobiapi/API_Docs_en/wiki/WS_api_reference_en
|
|
7
7
|
|
|
8
|
-
export class HuobiTradesMapper
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
export class HuobiTradesMapper implements Mapper<
|
|
9
|
+
'huobi' | 'huobi-dm' | 'huobi-dm-swap' | 'huobi-dm-linear-swap' | 'huobi-dm-options',
|
|
10
|
+
Trade
|
|
11
|
+
> {
|
|
11
12
|
constructor(private readonly _exchange: Exchange) {}
|
|
12
13
|
canHandle(message: HuobiDataMessage) {
|
|
13
14
|
if (message.ch === undefined) {
|
|
@@ -46,9 +47,10 @@ export class HuobiTradesMapper
|
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
49
|
|
|
49
|
-
export class HuobiBookChangeMapper
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
export class HuobiBookChangeMapper implements Mapper<
|
|
51
|
+
'huobi' | 'huobi-dm' | 'huobi-dm-swap' | 'huobi-dm-linear-swap' | 'huobi-dm-options',
|
|
52
|
+
BookChange
|
|
53
|
+
> {
|
|
52
54
|
constructor(protected readonly _exchange: Exchange) {}
|
|
53
55
|
|
|
54
56
|
canHandle(message: HuobiDataMessage) {
|
package/src/mappers/index.ts
CHANGED
|
@@ -27,7 +27,17 @@ import {
|
|
|
27
27
|
BitfinexTradesMapper
|
|
28
28
|
} from './bitfinex.ts'
|
|
29
29
|
import { BitflyerBookChangeMapper, bitflyerBookTickerMapper, bitflyerTradesMapper } from './bitflyer.ts'
|
|
30
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
BitgetBookChangeMapper,
|
|
32
|
+
BitgetBookTickerMapper,
|
|
33
|
+
BitgetDerivativeTickerMapper,
|
|
34
|
+
BitgetTradesMapper,
|
|
35
|
+
BitgetV3BookChangeMapper,
|
|
36
|
+
BitgetV3BookTickerMapper,
|
|
37
|
+
BitgetV3DerivativeTickerMapper,
|
|
38
|
+
BitgetV3LiquidationsMapper,
|
|
39
|
+
BitgetV3TradesMapper
|
|
40
|
+
} from './bitget.ts'
|
|
31
41
|
import {
|
|
32
42
|
BitmexBookChangeMapper,
|
|
33
43
|
BitmexDerivativeTickerMapper,
|
|
@@ -208,6 +218,12 @@ const shouldUseBybitAllLiquidationFeed = (localTimestamp: Date) => {
|
|
|
208
218
|
return isRealTime(localTimestamp) || localTimestamp.valueOf() >= BYBIT_V5_API_ALL_LIQUIDATION_SUPPORT_DATE.valueOf()
|
|
209
219
|
}
|
|
210
220
|
|
|
221
|
+
const BITGET_V3_API_SWITCH_DATE = new Date('2026-04-28T00:00:00.000Z')
|
|
222
|
+
|
|
223
|
+
const shouldUseBitgetV3Mappers = (localTimestamp: Date) => {
|
|
224
|
+
return isRealTime(localTimestamp) || localTimestamp.valueOf() >= BITGET_V3_API_SWITCH_DATE.valueOf()
|
|
225
|
+
}
|
|
226
|
+
|
|
211
227
|
const OKCOIN_V5_API_SWITCH_DATE = new Date('2023-04-27T00:00:00.000Z')
|
|
212
228
|
const shouldUseOkcoinV5Mappers = (localTimestamp: Date) => {
|
|
213
229
|
return isRealTime(localTimestamp) || localTimestamp.valueOf() >= OKCOIN_V5_API_SWITCH_DATE.valueOf()
|
|
@@ -320,8 +336,10 @@ const tradesMappers = {
|
|
|
320
336
|
? new BinanceEuropeanOptionsTradesMapperV2()
|
|
321
337
|
: new BinanceEuropeanOptionsTradesMapper(),
|
|
322
338
|
'okex-spreads': () => new OkexSpreadsTradesMapper(),
|
|
323
|
-
bitget: () =>
|
|
324
|
-
|
|
339
|
+
bitget: (localTimestamp: Date) =>
|
|
340
|
+
shouldUseBitgetV3Mappers(localTimestamp) ? new BitgetV3TradesMapper('bitget') : new BitgetTradesMapper('bitget'),
|
|
341
|
+
'bitget-futures': (localTimestamp: Date) =>
|
|
342
|
+
shouldUseBitgetV3Mappers(localTimestamp) ? new BitgetV3TradesMapper('bitget-futures') : new BitgetTradesMapper('bitget-futures'),
|
|
325
343
|
'coinbase-international': () => coinbaseInternationalTradesMapper,
|
|
326
344
|
hyperliquid: () => new HyperliquidTradesMapper(),
|
|
327
345
|
lighter: () => new LighterTradesMapper()
|
|
@@ -391,8 +409,8 @@ const bookChangeMappers = {
|
|
|
391
409
|
shouldUseGateIOV4OrderBookV2Mappers(localTimestamp)
|
|
392
410
|
? new GateIOV4OrderBookV2ChangeMapper('gate-io')
|
|
393
411
|
: shouldUseGateIOV4Mappers(localTimestamp)
|
|
394
|
-
|
|
395
|
-
|
|
412
|
+
? new GateIOV4BookChangeMapper('gate-io', isRealTime(localTimestamp) == false)
|
|
413
|
+
: new GateIOBookChangeMapper('gate-io'),
|
|
396
414
|
'gate-io-futures': () => new GateIOFuturesBookChangeMapper('gate-io-futures'),
|
|
397
415
|
poloniex: (localTimestamp: Date) =>
|
|
398
416
|
shouldUsePoloniexV2Mappers(localTimestamp) ? new PoloniexV2BookChangeMapper() : new PoloniexBookChangeMapper(),
|
|
@@ -416,8 +434,12 @@ const bookChangeMappers = {
|
|
|
416
434
|
? new BinanceEuropeanOptionsBookChangeMapperV2()
|
|
417
435
|
: new BinanceEuropeanOptionsBookChangeMapper(),
|
|
418
436
|
'okex-spreads': () => new OkexSpreadsBookChangeMapper(),
|
|
419
|
-
bitget: () =>
|
|
420
|
-
|
|
437
|
+
bitget: (localTimestamp: Date) =>
|
|
438
|
+
shouldUseBitgetV3Mappers(localTimestamp) ? new BitgetV3BookChangeMapper('bitget') : new BitgetBookChangeMapper('bitget'),
|
|
439
|
+
'bitget-futures': (localTimestamp: Date) =>
|
|
440
|
+
shouldUseBitgetV3Mappers(localTimestamp)
|
|
441
|
+
? new BitgetV3BookChangeMapper('bitget-futures')
|
|
442
|
+
: new BitgetBookChangeMapper('bitget-futures'),
|
|
421
443
|
'coinbase-international': () => new CoinbaseInternationalBookChangMapper(),
|
|
422
444
|
hyperliquid: () => new HyperliquidBookChangeMapper(),
|
|
423
445
|
lighter: () => new LighterBookChangeMapper()
|
|
@@ -454,7 +476,8 @@ const derivativeTickersMappers = {
|
|
|
454
476
|
'crypto-com': () => new CryptoComDerivativeTickerMapper('crypto-com'),
|
|
455
477
|
'woo-x': () => new WooxDerivativeTickerMapper(),
|
|
456
478
|
'kucoin-futures': () => new KucoinFuturesDerivativeTickerMapper(),
|
|
457
|
-
'bitget-futures': () =>
|
|
479
|
+
'bitget-futures': (localTimestamp: Date) =>
|
|
480
|
+
shouldUseBitgetV3Mappers(localTimestamp) ? new BitgetV3DerivativeTickerMapper() : new BitgetDerivativeTickerMapper(),
|
|
458
481
|
'coinbase-international': () => new CoinbaseInternationalDerivativeTickerMapper(),
|
|
459
482
|
hyperliquid: () => new HyperliquidDerivativeTickerMapper(),
|
|
460
483
|
lighter: () => new LighterDerivativeTickerMapper()
|
|
@@ -496,7 +519,8 @@ const liquidationsMappers = {
|
|
|
496
519
|
? new OkexV5LiquidationsMapper('okex-futures')
|
|
497
520
|
: new OkexLiquidationsMapper('okex-futures', 'futures'),
|
|
498
521
|
'okex-swap': (localTimestamp: Date) =>
|
|
499
|
-
shouldUseOkexV5Mappers(localTimestamp) ? new OkexV5LiquidationsMapper('okex-swap') : new OkexLiquidationsMapper('okex-swap', 'swap')
|
|
522
|
+
shouldUseOkexV5Mappers(localTimestamp) ? new OkexV5LiquidationsMapper('okex-swap') : new OkexLiquidationsMapper('okex-swap', 'swap'),
|
|
523
|
+
'bitget-futures': () => new BitgetV3LiquidationsMapper()
|
|
500
524
|
}
|
|
501
525
|
|
|
502
526
|
const bookTickersMappers = {
|
|
@@ -556,8 +580,12 @@ const bookTickersMappers = {
|
|
|
556
580
|
'gate-io': () => new GateIOV4BookTickerMapper('gate-io'),
|
|
557
581
|
'okex-spreads': () => new OkexSpreadsBookTickerMapper(),
|
|
558
582
|
'kucoin-futures': () => new KucoinFuturesBookTickerMapper(),
|
|
559
|
-
bitget: () =>
|
|
560
|
-
|
|
583
|
+
bitget: (localTimestamp: Date) =>
|
|
584
|
+
shouldUseBitgetV3Mappers(localTimestamp) ? new BitgetV3BookTickerMapper('bitget') : new BitgetBookTickerMapper('bitget'),
|
|
585
|
+
'bitget-futures': (localTimestamp: Date) =>
|
|
586
|
+
shouldUseBitgetV3Mappers(localTimestamp)
|
|
587
|
+
? new BitgetV3BookTickerMapper('bitget-futures')
|
|
588
|
+
: new BitgetBookTickerMapper('bitget-futures'),
|
|
561
589
|
'coinbase-international': () => coinbaseInternationalBookTickerMapper,
|
|
562
590
|
hyperliquid: () => new HyperliquidBookTickerMapper(),
|
|
563
591
|
lighter: () => new LighterBookTickerMapper(),
|
package/src/mappers/kucoin.ts
CHANGED
|
@@ -46,7 +46,10 @@ export class KucoinBookChangeMapper implements Mapper<'kucoin', BookChange> {
|
|
|
46
46
|
[key: string]: LocalDepthInfo
|
|
47
47
|
} = {}
|
|
48
48
|
|
|
49
|
-
constructor(
|
|
49
|
+
constructor(
|
|
50
|
+
protected readonly _exchange: Exchange,
|
|
51
|
+
private readonly ignoreBookSnapshotOverlapError: boolean
|
|
52
|
+
) {}
|
|
50
53
|
|
|
51
54
|
canHandle(message: KucoinLevel2SnapshotMessage | KucoinLevel2UpdateMessage) {
|
|
52
55
|
return message.type === 'message' && message.topic.startsWith('/market/level2')
|
package/src/mappers/okex.ts
CHANGED
|
@@ -6,7 +6,10 @@ import { Mapper, PendingTickerInfoHelper } from './mapper.ts'
|
|
|
6
6
|
// https://www.okex.com/docs-v5/en/#websocket-api-public-channel-trades-channel
|
|
7
7
|
|
|
8
8
|
export class OkexV5TradesMapper implements Mapper<OKEX_EXCHANGES, Trade> {
|
|
9
|
-
constructor(
|
|
9
|
+
constructor(
|
|
10
|
+
private readonly _exchange: Exchange,
|
|
11
|
+
private readonly _useTradesAll: boolean
|
|
12
|
+
) {}
|
|
10
13
|
|
|
11
14
|
canHandle(message: any) {
|
|
12
15
|
if (message.event !== undefined || message.arg === undefined) {
|
|
@@ -62,7 +65,10 @@ const mapV5BookLevel = (level: OkexV5BookLevel) => {
|
|
|
62
65
|
export class OkexV5BookChangeMapper implements Mapper<OKEX_EXCHANGES, BookChange> {
|
|
63
66
|
private _channelName: string
|
|
64
67
|
|
|
65
|
-
constructor(
|
|
68
|
+
constructor(
|
|
69
|
+
private readonly _exchange: Exchange,
|
|
70
|
+
usePublicBooksChannel: boolean
|
|
71
|
+
) {
|
|
66
72
|
this._channelName = this._getBooksChannelName(usePublicBooksChannel)
|
|
67
73
|
}
|
|
68
74
|
|
|
@@ -137,7 +143,10 @@ export class OkexV5BookChangeMapper implements Mapper<OKEX_EXCHANGES, BookChange
|
|
|
137
143
|
}
|
|
138
144
|
|
|
139
145
|
export class OkexV5BookTickerMapper implements Mapper<OKEX_EXCHANGES, BookTicker> {
|
|
140
|
-
constructor(
|
|
146
|
+
constructor(
|
|
147
|
+
private readonly _exchange: Exchange,
|
|
148
|
+
private readonly _useTbtTickerChannel: boolean
|
|
149
|
+
) {}
|
|
141
150
|
|
|
142
151
|
canHandle(message: any) {
|
|
143
152
|
if (message.event !== undefined || message.arg === undefined) {
|
|
@@ -726,7 +735,10 @@ type OkexV5SummaryMessage = {
|
|
|
726
735
|
// https://www.okex.com/docs/en/#ws_swap-README
|
|
727
736
|
|
|
728
737
|
export class OkexTradesMapper implements Mapper<OKEX_EXCHANGES, Trade> {
|
|
729
|
-
constructor(
|
|
738
|
+
constructor(
|
|
739
|
+
private readonly _exchange: Exchange,
|
|
740
|
+
private readonly _market: OKEX_MARKETS
|
|
741
|
+
) {}
|
|
730
742
|
|
|
731
743
|
canHandle(message: OkexDataMessage) {
|
|
732
744
|
return message.table === `${this._market}/trade`
|
|
@@ -991,7 +1003,10 @@ export class OkexOptionSummaryMapper implements Mapper<'okex-options', OptionSum
|
|
|
991
1003
|
}
|
|
992
1004
|
|
|
993
1005
|
export class OkexLiquidationsMapper implements Mapper<OKEX_EXCHANGES, Liquidation> {
|
|
994
|
-
constructor(
|
|
1006
|
+
constructor(
|
|
1007
|
+
private readonly _exchange: Exchange,
|
|
1008
|
+
private readonly _market: OKEX_MARKETS
|
|
1009
|
+
) {}
|
|
995
1010
|
|
|
996
1011
|
canHandle(message: OkexDataMessage) {
|
|
997
1012
|
return message.table === `${this._market}/liquidation`
|
|
@@ -1027,7 +1042,10 @@ export class OkexLiquidationsMapper implements Mapper<OKEX_EXCHANGES, Liquidatio
|
|
|
1027
1042
|
}
|
|
1028
1043
|
|
|
1029
1044
|
export class OkexBookTickerMapper implements Mapper<OKEX_EXCHANGES, BookTicker> {
|
|
1030
|
-
constructor(
|
|
1045
|
+
constructor(
|
|
1046
|
+
private readonly _exchange: Exchange,
|
|
1047
|
+
private readonly _market: OKEX_MARKETS
|
|
1048
|
+
) {}
|
|
1031
1049
|
|
|
1032
1050
|
canHandle(message: OkexDataMessage) {
|
|
1033
1051
|
return message.table === `${this._market}/ticker`
|
package/src/mappers/phemex.ts
CHANGED
|
@@ -27,6 +27,11 @@ function getQtyScale(symbol: string) {
|
|
|
27
27
|
return 1
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
function isExcludedFromNormalizedOutput(symbol: string) {
|
|
31
|
+
// Matches tardis-api metadata: Phemex spot OL/USDT uses sOLUSDT, which collides with SOLUSDT when normalized.
|
|
32
|
+
return symbol === 'sOLUSDT'
|
|
33
|
+
}
|
|
34
|
+
|
|
30
35
|
const COINS_STARTING_WITH_S = [
|
|
31
36
|
'SOLUSD',
|
|
32
37
|
'SUSHIUSD',
|
|
@@ -163,10 +168,13 @@ export const phemexTradesMapper: Mapper<'phemex', Trade> = {
|
|
|
163
168
|
},
|
|
164
169
|
|
|
165
170
|
*map(message: PhemexTradeMessage, localTimestamp: Date): IterableIterator<Trade> {
|
|
171
|
+
const symbol = message.symbol
|
|
172
|
+
if (isExcludedFromNormalizedOutput(symbol)) {
|
|
173
|
+
return
|
|
174
|
+
}
|
|
175
|
+
|
|
166
176
|
if ('trades' in message) {
|
|
167
177
|
for (const [timestamp, side, priceEp, qty] of message.trades) {
|
|
168
|
-
const symbol = message.symbol
|
|
169
|
-
|
|
170
178
|
yield {
|
|
171
179
|
type: 'trade',
|
|
172
180
|
symbol: symbol.toUpperCase(),
|
|
@@ -181,8 +189,6 @@ export const phemexTradesMapper: Mapper<'phemex', Trade> = {
|
|
|
181
189
|
}
|
|
182
190
|
} else if ('trades_p' in message) {
|
|
183
191
|
for (const [timestamp, side, price, qty] of message.trades_p) {
|
|
184
|
-
const symbol = message.symbol
|
|
185
|
-
|
|
186
192
|
yield {
|
|
187
193
|
type: 'trade',
|
|
188
194
|
symbol: symbol.toUpperCase(),
|
|
@@ -253,6 +259,10 @@ export const phemexBookChangeMapper: Mapper<'phemex', BookChange> = {
|
|
|
253
259
|
|
|
254
260
|
*map(message: PhemexBookMessage, localTimestamp: Date): IterableIterator<BookChange> {
|
|
255
261
|
const symbol = message.symbol
|
|
262
|
+
if (isExcludedFromNormalizedOutput(symbol)) {
|
|
263
|
+
return
|
|
264
|
+
}
|
|
265
|
+
|
|
256
266
|
if ('book' in message) {
|
|
257
267
|
const mapBookLevel = mapBookLevelForSymbol(symbol)
|
|
258
268
|
yield {
|