tardis-dev 13.4.10 → 13.4.13

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.
Files changed (87) hide show
  1. package/dist/consts.d.ts +6 -2
  2. package/dist/consts.d.ts.map +1 -1
  3. package/dist/consts.js +26 -3
  4. package/dist/consts.js.map +1 -1
  5. package/dist/mappers/bybit.d.ts +1 -1
  6. package/dist/mappers/bybitspot.d.ts +96 -0
  7. package/dist/mappers/bybitspot.d.ts.map +1 -0
  8. package/dist/mappers/bybitspot.js +102 -0
  9. package/dist/mappers/bybitspot.js.map +1 -0
  10. package/dist/mappers/cryptocom.d.ts +257 -0
  11. package/dist/mappers/cryptocom.d.ts.map +1 -0
  12. package/dist/mappers/cryptocom.js +193 -0
  13. package/dist/mappers/cryptocom.js.map +1 -0
  14. package/dist/mappers/huobi.d.ts +3 -3
  15. package/dist/mappers/index.d.ts +4 -4
  16. package/dist/mappers/index.d.ts.map +1 -1
  17. package/dist/mappers/index.js +25 -6
  18. package/dist/mappers/index.js.map +1 -1
  19. package/dist/mappers/poloniex.d.ts +60 -0
  20. package/dist/mappers/poloniex.d.ts.map +1 -1
  21. package/dist/mappers/poloniex.js +73 -2
  22. package/dist/mappers/poloniex.js.map +1 -1
  23. package/dist/mappers/serum.d.ts +12 -0
  24. package/dist/mappers/serum.d.ts.map +1 -1
  25. package/dist/mappers/serum.js +2 -2
  26. package/dist/mappers/serum.js.map +1 -1
  27. package/dist/realtimefeeds/ascendex.d.ts +2 -0
  28. package/dist/realtimefeeds/ascendex.d.ts.map +1 -1
  29. package/dist/realtimefeeds/ascendex.js +6 -0
  30. package/dist/realtimefeeds/ascendex.js.map +1 -1
  31. package/dist/realtimefeeds/bybit.d.ts +2 -0
  32. package/dist/realtimefeeds/bybit.d.ts.map +1 -1
  33. package/dist/realtimefeeds/bybit.js +6 -0
  34. package/dist/realtimefeeds/bybit.js.map +1 -1
  35. package/dist/realtimefeeds/bybitspot.d.ts +10 -0
  36. package/dist/realtimefeeds/bybitspot.d.ts.map +1 -0
  37. package/dist/realtimefeeds/bybitspot.js +40 -0
  38. package/dist/realtimefeeds/bybitspot.js.map +1 -0
  39. package/dist/realtimefeeds/cryptocom.d.ts +10 -0
  40. package/dist/realtimefeeds/cryptocom.d.ts.map +1 -0
  41. package/dist/realtimefeeds/cryptocom.js +49 -0
  42. package/dist/realtimefeeds/cryptocom.js.map +1 -0
  43. package/dist/realtimefeeds/cryptocomderivatives.d.ts +10 -0
  44. package/dist/realtimefeeds/cryptocomderivatives.d.ts.map +1 -0
  45. package/dist/realtimefeeds/cryptocomderivatives.js +51 -0
  46. package/dist/realtimefeeds/cryptocomderivatives.js.map +1 -0
  47. package/dist/realtimefeeds/delta.d.ts +2 -0
  48. package/dist/realtimefeeds/delta.d.ts.map +1 -1
  49. package/dist/realtimefeeds/delta.js +6 -0
  50. package/dist/realtimefeeds/delta.js.map +1 -1
  51. package/dist/realtimefeeds/ftx.d.ts +2 -0
  52. package/dist/realtimefeeds/ftx.d.ts.map +1 -1
  53. package/dist/realtimefeeds/ftx.js +6 -0
  54. package/dist/realtimefeeds/ftx.js.map +1 -1
  55. package/dist/realtimefeeds/index.d.ts.map +1 -1
  56. package/dist/realtimefeeds/index.js +9 -1
  57. package/dist/realtimefeeds/index.js.map +1 -1
  58. package/dist/realtimefeeds/mango.d.ts +5 -0
  59. package/dist/realtimefeeds/mango.d.ts.map +1 -0
  60. package/dist/realtimefeeds/mango.js +12 -0
  61. package/dist/realtimefeeds/mango.js.map +1 -0
  62. package/dist/realtimefeeds/poloniex.d.ts +6 -3
  63. package/dist/realtimefeeds/poloniex.d.ts.map +1 -1
  64. package/dist/realtimefeeds/poloniex.js +14 -9
  65. package/dist/realtimefeeds/poloniex.js.map +1 -1
  66. package/dist/realtimefeeds/realtimefeed.d.ts +1 -0
  67. package/dist/realtimefeeds/realtimefeed.d.ts.map +1 -1
  68. package/dist/realtimefeeds/realtimefeed.js +7 -1
  69. package/dist/realtimefeeds/realtimefeed.js.map +1 -1
  70. package/package.json +1 -1
  71. package/src/consts.ts +30 -3
  72. package/src/mappers/bybitspot.ts +129 -0
  73. package/src/mappers/cryptocom.ts +395 -0
  74. package/src/mappers/index.ts +30 -8
  75. package/src/mappers/poloniex.ts +134 -1
  76. package/src/mappers/serum.ts +27 -13
  77. package/src/realtimefeeds/ascendex.ts +8 -0
  78. package/src/realtimefeeds/bybit.ts +8 -0
  79. package/src/realtimefeeds/bybitspot.ts +39 -0
  80. package/src/realtimefeeds/cryptocom.ts +48 -0
  81. package/src/realtimefeeds/cryptocomderivatives.ts +50 -0
  82. package/src/realtimefeeds/delta.ts +8 -0
  83. package/src/realtimefeeds/ftx.ts +8 -0
  84. package/src/realtimefeeds/index.ts +9 -1
  85. package/src/realtimefeeds/mango.ts +5 -0
  86. package/src/realtimefeeds/poloniex.ts +16 -10
  87. package/src/realtimefeeds/realtimefeed.ts +7 -1
@@ -0,0 +1,395 @@
1
+ import { upperCaseSymbols } from '../handy'
2
+ import { BookChange, Exchange, BookTicker, Trade, DerivativeTicker } from '../types'
3
+ import { Mapper, PendingTickerInfoHelper } from './mapper'
4
+
5
+ export class CryptoComTradesMapper implements Mapper<'crypto-com' | 'crypto-com-derivatives', Trade> {
6
+ constructor(private readonly _exchange: Exchange) {}
7
+ canHandle(message: CryptoComTradeMessage) {
8
+ return message.result !== undefined && message.result.channel === 'trade'
9
+ }
10
+
11
+ getFilters(symbols?: string[]) {
12
+ symbols = upperCaseSymbols(symbols)
13
+
14
+ return [
15
+ {
16
+ channel: 'trade',
17
+ symbols
18
+ } as const
19
+ ]
20
+ }
21
+
22
+ *map(message: CryptoComTradeMessage, localTimestamp: Date): IterableIterator<Trade> {
23
+ message.result.data.reverse()
24
+
25
+ for (const item of message.result.data) {
26
+ const trade: Trade = {
27
+ type: 'trade',
28
+ symbol: message.result.instrument_name,
29
+ exchange: this._exchange,
30
+ id: item.d.toString(),
31
+ price: Number(item.p),
32
+ amount: Number(item.q),
33
+ side: item.s === 'BUY' ? 'buy' : 'sell',
34
+ timestamp: new Date(item.t),
35
+ localTimestamp
36
+ }
37
+
38
+ yield trade
39
+ }
40
+ }
41
+ }
42
+
43
+ export class CryptoComBookChangeMapper implements Mapper<'crypto-com' | 'crypto-com-derivatives', BookChange> {
44
+ constructor(protected readonly _exchange: Exchange) {}
45
+
46
+ canHandle(message: CryptoComBookMessage) {
47
+ return message.result !== undefined && message.result.channel.startsWith('book')
48
+ }
49
+
50
+ getFilters(symbols?: string[]) {
51
+ symbols = upperCaseSymbols(symbols)
52
+ return [
53
+ {
54
+ channel: 'book',
55
+ symbols
56
+ } as const
57
+ ]
58
+ }
59
+
60
+ *map(message: CryptoComBookMessage, localTimestamp: Date) {
61
+ if (message.result.data === undefined || message.result.data[0] === undefined) {
62
+ return
63
+ }
64
+
65
+ const bids = (message.result.channel === 'book' ? message.result.data[0].bids : message.result.data[0].update.bids) || []
66
+ const asks = (message.result.channel === 'book' ? message.result.data[0].asks : message.result.data[0].update.asks) || []
67
+
68
+ yield {
69
+ type: 'book_change',
70
+ symbol: message.result.instrument_name,
71
+ exchange: this._exchange,
72
+ isSnapshot: message.result.channel === 'book',
73
+ bids: bids.map(this._mapBookLevel),
74
+ asks: asks.map(this._mapBookLevel),
75
+ timestamp: new Date(message.result.data[0].t),
76
+ localTimestamp
77
+ } as const
78
+ }
79
+
80
+ private _mapBookLevel(level: [number | string, number | string]) {
81
+ return { price: Number(level[0]), amount: Number(level[1]) }
82
+ }
83
+ }
84
+
85
+ export class CryptoComBookTickerMapper implements Mapper<'crypto-com' | 'crypto-com-derivatives', BookTicker> {
86
+ constructor(protected readonly _exchange: Exchange) {}
87
+
88
+ canHandle(message: CryptoComTickerMessage) {
89
+ return message.result !== undefined && message.result.channel === 'ticker'
90
+ }
91
+
92
+ getFilters(symbols?: string[]) {
93
+ symbols = upperCaseSymbols(symbols)
94
+ return [
95
+ {
96
+ channel: 'ticker',
97
+ symbols
98
+ } as const
99
+ ]
100
+ }
101
+
102
+ *map(message: CryptoComTickerMessage, localTimestamp: Date) {
103
+ for (const item of message.result.data) {
104
+ const bookTicker: BookTicker = {
105
+ type: 'book_ticker',
106
+ symbol: message.result.instrument_name,
107
+ exchange: this._exchange,
108
+
109
+ askAmount: undefined,
110
+ askPrice: item.k !== undefined && item.k !== null ? Number(item.k) : undefined,
111
+ bidPrice: item.b !== undefined && item.b !== null ? Number(item.b) : undefined,
112
+ bidAmount: undefined,
113
+ timestamp: new Date(item.t),
114
+ localTimestamp: localTimestamp
115
+ }
116
+
117
+ yield bookTicker
118
+ }
119
+ }
120
+ }
121
+
122
+ export class CryptoComDerivativeTickerMapper implements Mapper<'crypto-com-derivatives', DerivativeTicker> {
123
+ private readonly pendingTickerInfoHelper = new PendingTickerInfoHelper()
124
+ private readonly _indexPrices = new Map<string, number>()
125
+
126
+ constructor(protected readonly exchange: Exchange) {}
127
+
128
+ canHandle(message: CryptoComDerivativesTickerMessage | CryptoComIndexMessage | CryptoComMarkPriceMessage | CryptoComFundingMessage) {
129
+ if (message.result === undefined) {
130
+ return false
131
+ }
132
+
133
+ return (
134
+ message.result.channel === 'ticker' ||
135
+ message.result.channel === 'index' ||
136
+ message.result.channel === 'mark' ||
137
+ message.result.channel === 'funding'
138
+ )
139
+ }
140
+
141
+ getFilters(symbols?: string[]) {
142
+ symbols = upperCaseSymbols(symbols)
143
+
144
+ let indexes: string[] = []
145
+ if (symbols !== undefined) {
146
+ indexes = [...new Set(symbols.map((s) => `${s.split('-')[0]}-INDEX`))]
147
+ }
148
+ const filters = [
149
+ {
150
+ channel: 'ticker',
151
+ symbols
152
+ } as const,
153
+ {
154
+ channel: 'index',
155
+ symbols: indexes
156
+ } as const,
157
+ {
158
+ channel: 'mark',
159
+ symbols
160
+ } as const,
161
+ {
162
+ channel: 'funding',
163
+ symbols
164
+ } as const
165
+ ]
166
+
167
+ return filters
168
+ }
169
+
170
+ *map(
171
+ message: CryptoComDerivativesTickerMessage | CryptoComIndexMessage | CryptoComMarkPriceMessage | CryptoComFundingMessage,
172
+ localTimestamp: Date
173
+ ): IterableIterator<DerivativeTicker> {
174
+ if (message.result.channel === 'index') {
175
+ this._indexPrices.set(message.result.instrument_name.split('-')[0], Number(message.result.data[0].v))
176
+ return
177
+ }
178
+
179
+ const pendingTickerInfo = this.pendingTickerInfoHelper.getPendingTickerInfo(message.result.instrument_name, this.exchange)
180
+
181
+ const lastIndexPrice = this._indexPrices.get(message.result.instrument_name.split('-')[0])
182
+ if (lastIndexPrice !== undefined) {
183
+ pendingTickerInfo.updateIndexPrice(lastIndexPrice)
184
+ }
185
+
186
+ if (message.result.channel === 'ticker') {
187
+ if (message.result.data[0].a !== null && message.result.data[0].a !== undefined) {
188
+ pendingTickerInfo.updateLastPrice(Number(message.result.data[0].a))
189
+ }
190
+ if (message.result.data[0].oi !== null && message.result.data[0].oi !== undefined) {
191
+ pendingTickerInfo.updateOpenInterest(Number(message.result.data[0].oi))
192
+ }
193
+ }
194
+
195
+ if (message.result.channel === 'mark') {
196
+ if (message.result.data[0].v !== null && message.result.data[0].v !== undefined) {
197
+ pendingTickerInfo.updateMarkPrice(Number(message.result.data[0].v))
198
+ }
199
+ }
200
+
201
+ if (message.result.channel === 'funding') {
202
+ if (message.result.data[0].v !== null && message.result.data[0].v !== undefined) {
203
+ pendingTickerInfo.updateFundingRate(Number(message.result.data[0].v))
204
+ const nextFundingTimestamp = new Date(message.result.data[0].t)
205
+ nextFundingTimestamp.setUTCHours(nextFundingTimestamp.getUTCHours() + 1)
206
+ nextFundingTimestamp.setUTCMinutes(0, 0, 0)
207
+ pendingTickerInfo.updateFundingTimestamp(nextFundingTimestamp)
208
+ }
209
+ }
210
+
211
+ pendingTickerInfo.updateTimestamp(new Date(message.result.data[0].t))
212
+
213
+ if (pendingTickerInfo.hasChanged()) {
214
+ yield pendingTickerInfo.getSnapshot(localTimestamp)
215
+ }
216
+ }
217
+ }
218
+
219
+ type CryptoComTradeMessage =
220
+ | {
221
+ method: 'subscribe'
222
+ result: {
223
+ instrument_name: 'ETH_CRO' // instrument_name
224
+ subscription: 'trade.ETH_CRO'
225
+ channel: 'trade'
226
+ data: [
227
+ {
228
+ p: 162.12 // price
229
+ q: 11.085 // quantity
230
+ s: 'BUY' // side
231
+ d: 1210447366 // trade id
232
+ t: 1587523078844 // trade time
233
+ dataTime: 0 // please ignore this field
234
+ }
235
+ ]
236
+ }
237
+ }
238
+ | {
239
+ id: -1
240
+ code: 0
241
+ method: 'subscribe'
242
+ result: {
243
+ channel: 'trade'
244
+ subscription: 'trade.BTCUSD-PERP'
245
+ instrument_name: 'BTCUSD-PERP'
246
+ data: [{ d: '4611686018439397540'; t: 1653992578435; p: '31603.5'; q: '0.1000'; s: 'BUY'; i: 'BTCUSD-PERP' }]
247
+ }
248
+ }
249
+
250
+ type CryptoComBookMessage =
251
+ | {
252
+ code: 0
253
+ method: 'subscribe'
254
+ result: {
255
+ instrument_name: 'ETH_CRO'
256
+ subscription: 'book.ETH_CRO.150'
257
+ channel: 'book'
258
+ depth: 150
259
+ data: [
260
+ {
261
+ bids: [number, number][]
262
+ asks: [number, number][]
263
+ t: 1659311999933
264
+ s: 788293808
265
+ }
266
+ ]
267
+ }
268
+ }
269
+ | {
270
+ code: 0
271
+ method: 'subscribe'
272
+ result: {
273
+ instrument_name: 'DOT_USDT'
274
+ subscription: 'book.DOT_USDT.150'
275
+ channel: 'book.update'
276
+ depth: 150
277
+ data: [
278
+ {
279
+ update: { bids: [number, number][]; asks: [number, number][] }
280
+ t: 1659312000046
281
+ s: 763793123
282
+ }
283
+ ]
284
+ }
285
+ }
286
+ | {
287
+ id: -1
288
+ code: 0
289
+ method: 'subscribe'
290
+ result: {
291
+ channel: 'book.update'
292
+ subscription: 'book.BTCUSD-PERP.50'
293
+ instrument_name: 'BTCUSD-PERP'
294
+ depth: 50
295
+ data: [
296
+ {
297
+ update: { asks: [string, string][]; bids: [string, string][] }
298
+ t: 1653992578436
299
+ tt: 1653992578428
300
+ u: 72560693920
301
+ pu: 72560688000
302
+ cs: 380529173
303
+ }
304
+ ]
305
+ }
306
+ }
307
+
308
+ type CryptoComTickerMessage =
309
+ | {
310
+ code: 0
311
+ method: 'subscribe'
312
+ result: {
313
+ instrument_name: 'GODS_USDT'
314
+ subscription: 'ticker.GODS_USDT'
315
+ channel: 'ticker'
316
+ data: [
317
+ {
318
+ i: 'GODS_USDT'
319
+ b: 0.4262
320
+ k: 0.4272
321
+ a: 0.4272
322
+ t: 1659311999946
323
+ v: 100623.01
324
+ vv: 42986.1541
325
+ h: 0.4624
326
+ l: 0.4229
327
+ c: -0.0062
328
+ pc: -1.4302
329
+ }
330
+ ]
331
+ }
332
+ }
333
+ | CryptoComDerivativesTickerMessage
334
+
335
+ type CryptoComDerivativesTickerMessage = {
336
+ id: -1
337
+ code: 0
338
+ method: 'subscribe'
339
+ result: {
340
+ channel: 'ticker'
341
+ instrument_name: 'BTCUSD-PERP'
342
+ subscription: 'ticker.BTCUSD-PERP'
343
+ data: [
344
+ {
345
+ h: '32222.5'
346
+ l: '30240.0'
347
+ a: '31611.0'
348
+ c: '0.0320'
349
+ b: '31613.0'
350
+ k: '31613.5'
351
+ i: 'BTCUSD-PERP'
352
+ v: '13206.4884'
353
+ vv: '433945264.39'
354
+ oi: '318.5162'
355
+ t: 1653992543383
356
+ }
357
+ ]
358
+ }
359
+ }
360
+
361
+ type CryptoComIndexMessage = {
362
+ id: -1
363
+ method: 'subscribe'
364
+ code: 0
365
+ result: {
366
+ instrument_name: 'BTCUSD-INDEX'
367
+ subscription: 'index.BTCUSD-INDEX'
368
+ channel: 'index'
369
+ data: [{ v: '31601.35'; t: 1653992545000 }]
370
+ }
371
+ }
372
+
373
+ type CryptoComMarkPriceMessage = {
374
+ id: 1
375
+ method: 'subscribe'
376
+ code: 0
377
+ result: {
378
+ instrument_name: 'BTCUSD-PERP'
379
+ subscription: 'mark.BTCUSD-PERP'
380
+ channel: 'mark'
381
+ data: [{ v: '31606.3'; t: 1653992543000 }]
382
+ }
383
+ }
384
+
385
+ type CryptoComFundingMessage = {
386
+ id: -1
387
+ method: 'subscribe'
388
+ code: 0
389
+ result: {
390
+ instrument_name: 'BTCUSD-PERP'
391
+ subscription: 'funding.BTCUSD-PERP'
392
+ channel: 'funding'
393
+ data: [{ v: '0.00000700'; t: 1653992579000 }]
394
+ }
395
+ }
@@ -28,8 +28,10 @@ import {
28
28
  } from './bitmex'
29
29
  import { BitstampBookChangeMapper, bitstampTradesMapper } from './bitstamp'
30
30
  import { BybitBookChangeMapper, BybitDerivativeTickerMapper, BybitLiquidationsMapper, BybitTradesMapper } from './bybit'
31
+ import { BybitSpotBookChangeMapper, BybitSpotBookTickerMapper, BybitSpotTradesMapper } from './bybitspot'
31
32
  import { CoinbaseBookChangMapper, coinbaseBookTickerMapper, coinbaseTradesMapper } from './coinbase'
32
33
  import { coinflexBookChangeMapper, CoinflexDerivativeTickerMapper, coinflexTradesMapper } from './coinflex'
34
+ import { CryptoComBookChangeMapper, CryptoComBookTickerMapper, CryptoComDerivativeTickerMapper, CryptoComTradesMapper } from './cryptocom'
33
35
  import {
34
36
  cryptofacilitiesBookChangeMapper,
35
37
  CryptofacilitiesDerivativeTickerMapper,
@@ -83,7 +85,7 @@ import {
83
85
  OkexV5TradesMapper
84
86
  } from './okex'
85
87
  import { phemexBookChangeMapper, PhemexDerivativeTickerMapper, phemexTradesMapper } from './phemex'
86
- import { PoloniexBookChangeMapper, PoloniexTradesMapper } from './poloniex'
88
+ import { PoloniexBookChangeMapper, PoloniexTradesMapper, PoloniexV2BookChangeMapper, PoloniexV2TradesMapper } from './poloniex'
87
89
  import { SerumBookChangeMapper, SerumBookTickerMapper, SerumTradesMapper } from './serum'
88
90
  import { UpbitBookChangeMapper, UpbitTradesMapper } from './upbit'
89
91
 
@@ -108,6 +110,12 @@ const canUseOkexTbtBookTicker = (localTimestamp: Date) => {
108
110
  return isRealTime(localTimestamp) || localTimestamp.valueOf() >= OKEX_V5_TBT_BOOK_TICKER_RELEASE_DATE.valueOf()
109
111
  }
110
112
 
113
+ const POLONIEX_V2_API_SWITCH_DATE = new Date('2022-08-02T00:00:00.000Z')
114
+
115
+ const shouldUsePoloniexV2Mappers = (localTimestamp: Date) => {
116
+ return isRealTime(localTimestamp) || localTimestamp.valueOf() >= POLONIEX_V2_API_SWITCH_DATE.valueOf()
117
+ }
118
+
111
119
  const tradesMappers = {
112
120
  bitmex: () => bitmexTradesMapper,
113
121
  binance: () => new BinanceTradesMapper('binance'),
@@ -151,14 +159,19 @@ const tradesMappers = {
151
159
  delta: (localTimestamp: Date) => new DeltaTradesMapper(localTimestamp.valueOf() >= new Date('2020-10-14').valueOf()),
152
160
  'gate-io': () => new GateIOTradesMapper('gate-io'),
153
161
  'gate-io-futures': () => new GateIOFuturesTradesMapper('gate-io-futures'),
154
- poloniex: () => new PoloniexTradesMapper(),
162
+ poloniex: (localTimestamp: Date) =>
163
+ shouldUsePoloniexV2Mappers(localTimestamp) ? new PoloniexV2TradesMapper() : new PoloniexTradesMapper(),
155
164
  coinflex: () => coinflexTradesMapper,
156
165
  'binance-options': () => new BinanceOptionsTradesMapper(),
157
166
  upbit: () => new UpbitTradesMapper(),
158
167
  ascendex: () => new AscendexTradesMapper(),
159
168
  dydx: () => new DydxTradesMapper(),
160
169
  serum: () => new SerumTradesMapper('serum'),
161
- 'star-atlas': () => new SerumTradesMapper('star-atlas')
170
+ 'star-atlas': () => new SerumTradesMapper('star-atlas'),
171
+ mango: () => new SerumTradesMapper('mango'),
172
+ 'bybit-spot': () => new BybitSpotTradesMapper('bybit-spot'),
173
+ 'crypto-com': () => new CryptoComTradesMapper('crypto-com'),
174
+ 'crypto-com-derivatives': () => new CryptoComTradesMapper('crypto-com-derivatives')
162
175
  }
163
176
 
164
177
  const bookChangeMappers = {
@@ -208,7 +221,7 @@ const bookChangeMappers = {
208
221
  'huobi-dm-swap': () => new HuobiBookChangeMapper('huobi-dm-swap'),
209
222
  'huobi-dm-linear-swap': () => new HuobiBookChangeMapper('huobi-dm-linear-swap'),
210
223
  'huobi-dm-options': () => new HuobiBookChangeMapper('huobi-dm-options'),
211
-
224
+ 'bybit-spot': () => new BybitSpotBookChangeMapper('bybit-spot'),
212
225
  bybit: () => new BybitBookChangeMapper('bybit', false),
213
226
  okcoin: (localTimestamp: Date) =>
214
227
  new OkexBookChangeMapper('okcoin', 'spot', localTimestamp.valueOf() >= new Date('2020-02-13').valueOf()),
@@ -217,14 +230,18 @@ const bookChangeMappers = {
217
230
  delta: () => deltaBookChangeMapper,
218
231
  'gate-io': () => new GateIOBookChangeMapper('gate-io'),
219
232
  'gate-io-futures': () => new GateIOFuturesBookChangeMapper('gate-io-futures'),
220
- poloniex: () => new PoloniexBookChangeMapper(),
233
+ poloniex: (localTimestamp: Date) =>
234
+ shouldUsePoloniexV2Mappers(localTimestamp) ? new PoloniexV2BookChangeMapper() : new PoloniexBookChangeMapper(),
221
235
  coinflex: () => coinflexBookChangeMapper,
222
236
  'binance-options': () => new BinanceOptionsBookChangeMapper(),
223
237
  upbit: () => new UpbitBookChangeMapper(),
224
238
  ascendex: () => new AscendexBookChangeMapper(),
225
239
  dydx: () => new DydxBookChangeMapper(),
226
240
  serum: () => new SerumBookChangeMapper('serum'),
227
- 'star-atlas': () => new SerumBookChangeMapper('star-atlas')
241
+ 'star-atlas': () => new SerumBookChangeMapper('star-atlas'),
242
+ mango: () => new SerumBookChangeMapper('mango'),
243
+ 'crypto-com': () => new CryptoComBookChangeMapper('crypto-com'),
244
+ 'crypto-com-derivatives': () => new CryptoComBookChangeMapper('crypto-com-derivatives')
228
245
  }
229
246
 
230
247
  const derivativeTickersMappers = {
@@ -252,7 +269,8 @@ const derivativeTickersMappers = {
252
269
  'gate-io-futures': () => new GateIOFuturesDerivativeTickerMapper(),
253
270
  coinflex: () => new CoinflexDerivativeTickerMapper(),
254
271
  ascendex: () => new AscendexDerivativeTickerMapper(),
255
- dydx: () => new DydxDerivativeTickerMapper()
272
+ dydx: () => new DydxDerivativeTickerMapper(),
273
+ 'crypto-com-derivatives': () => new CryptoComDerivativeTickerMapper('crypto-com-derivatives')
256
274
  }
257
275
 
258
276
  const optionsSummaryMappers = {
@@ -327,7 +345,11 @@ const bookTickersMappers = {
327
345
  okcoin: () => new OkexBookTickerMapper('okcoin', 'spot'),
328
346
  serum: () => new SerumBookTickerMapper('serum'),
329
347
  'star-atlas': () => new SerumBookTickerMapper('star-atlas'),
330
- 'gate-io-futures': () => new GateIOFuturesBookTickerMapper('gate-io-futures')
348
+ mango: () => new SerumBookTickerMapper('mango'),
349
+ 'gate-io-futures': () => new GateIOFuturesBookTickerMapper('gate-io-futures'),
350
+ 'bybit-spot': () => new BybitSpotBookTickerMapper('bybit-spot'),
351
+ 'crypto-com': () => new CryptoComBookTickerMapper('crypto-com'),
352
+ 'crypto-com-derivatives': () => new CryptoComBookTickerMapper('crypto-com-derivatives')
331
353
  }
332
354
 
333
355
  export const normalizeTrades = <T extends keyof typeof tradesMappers>(exchange: T, localTimestamp: Date): Mapper<T, Trade> => {
@@ -2,12 +2,87 @@ import { upperCaseSymbols } from '../handy'
2
2
  import { BookChange, Trade } from '../types'
3
3
  import { Mapper } from './mapper'
4
4
 
5
- // https://docs.poloniex.com/#websocket-api
5
+ export class PoloniexV2TradesMapper implements Mapper<'poloniex', Trade> {
6
+ canHandle(message: any) {
7
+ return message.channel === 'trades' && message.data !== undefined && message.data.length > 0
8
+ }
9
+
10
+ getFilters(symbols?: string[]) {
11
+ symbols = upperCaseSymbols(symbols)
12
+
13
+ return [
14
+ {
15
+ channel: 'trades',
16
+ symbols
17
+ } as const
18
+ ]
19
+ }
20
+
21
+ *map(message: PoloniexV2TradesMessage, localTimestamp: Date): IterableIterator<Trade> {
22
+ for (const item of message.data) {
23
+ yield {
24
+ type: 'trade',
25
+ symbol: item.symbol,
26
+ exchange: 'poloniex',
27
+ id: item.id,
28
+ price: Number(item.price),
29
+ amount: Number(item.quantity),
30
+ side: item.takerSide === 'sell' ? 'sell' : 'buy',
31
+ timestamp: new Date(item.createTime),
32
+ localTimestamp: localTimestamp
33
+ }
34
+ }
35
+ }
36
+ }
37
+
38
+ const mapBookLevelV2 = (level: [string, string]) => {
39
+ return {
40
+ price: Number(level[0]),
41
+ amount: Number(level[1])
42
+ }
43
+ }
44
+ export class PoloniexV2BookChangeMapper implements Mapper<'poloniex', BookChange> {
45
+ canHandle(message: any) {
46
+ return message.channel === 'book_lv2' && message.data !== undefined && message.data.length > 0
47
+ }
48
+
49
+ getFilters(symbols?: string[]) {
50
+ symbols = upperCaseSymbols(symbols)
51
+
52
+ return [
53
+ {
54
+ channel: 'book_lv2',
55
+ symbols
56
+ } as const
57
+ ]
58
+ }
59
+
60
+ *map(message: PoloniexV2BookMessage, localTimestamp: Date): IterableIterator<BookChange> {
61
+ for (const item of message.data) {
62
+ const bookSnapshot: BookChange = {
63
+ type: 'book_change',
64
+ symbol: item.symbol,
65
+ exchange: 'poloniex',
66
+ isSnapshot: message.action === 'snapshot',
67
+ bids: item.bids.map(mapBookLevelV2),
68
+ asks: item.asks.map(mapBookLevelV2),
69
+ timestamp: new Date(item.ts),
70
+ localTimestamp: localTimestamp
71
+ }
72
+
73
+ yield bookSnapshot
74
+ }
75
+ }
76
+ }
6
77
 
7
78
  export class PoloniexTradesMapper implements Mapper<'poloniex', Trade> {
8
79
  private readonly _channelIdToSymbolMap: Map<number, string> = new Map()
9
80
 
10
81
  canHandle(message: PoloniexPriceAggreatedMessage) {
82
+ if (Array.isArray(message) === false) {
83
+ return false
84
+ }
85
+
11
86
  if (message.length < 3) {
12
87
  return false
13
88
  }
@@ -80,6 +155,10 @@ export class PoloniexBookChangeMapper implements Mapper<'poloniex', BookChange>
80
155
  private readonly _channelIdToSymbolMap: Map<number, string> = new Map()
81
156
 
82
157
  canHandle(message: PoloniexPriceAggreatedMessage) {
158
+ if (Array.isArray(message) === false) {
159
+ return false
160
+ }
161
+
83
162
  if (message.length < 3) {
84
163
  return false
85
164
  }
@@ -153,3 +232,57 @@ type PoloniexBookUpdate = ['o', 0 | 1, string, string]
153
232
  type PoloniexTrade = ['t', string, 1 | 0, string, string, number]
154
233
 
155
234
  type PoloniexPriceAggreatedMessage = [number, number, (PoloniexBookSnapshot | PoloniexBookUpdate | PoloniexTrade)[], string?]
235
+
236
+ type PoloniexV2SubscribeMessage = {
237
+ event: 'subscribe'
238
+ channel: 'trades'
239
+ symbols: string[]
240
+ }
241
+
242
+ type PoloniexV2TradesMessage = {
243
+ channel: 'trades'
244
+ data: [
245
+ {
246
+ symbol: 'USDD_USDT'
247
+ amount: '53.17153856'
248
+ quantity: '53.0866'
249
+ takerSide: 'sell'
250
+ createTime: 1659916859838
251
+ price: '1.0016'
252
+ id: '60100203'
253
+ ts: 1659916859843
254
+ }
255
+ ]
256
+ }
257
+
258
+ type PoloniexV2BookMessage =
259
+ | {
260
+ channel: 'book_lv2'
261
+ data: [
262
+ {
263
+ symbol: 'AAVE_BTC'
264
+ createTime: 1659916859818
265
+ asks: [string, string][]
266
+ bids: [string, string][]
267
+ lastId: 20251
268
+ id: 20252
269
+ ts: 1659916859824
270
+ }
271
+ ]
272
+ action: 'update'
273
+ }
274
+ | {
275
+ channel: 'book_lv2'
276
+ data: [
277
+ {
278
+ symbol: 'AAVE_BTC'
279
+ createTime: 1659900600092
280
+ asks: [string, string][]
281
+ bids: [string, string][]
282
+ lastId: 85
283
+ id: 86
284
+ ts: 1659916800614
285
+ }
286
+ ]
287
+ action: 'snapshot'
288
+ }