tardis-dev 13.0.0 → 13.1.3

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 (142) hide show
  1. package/dist/consts.d.ts +4 -4
  2. package/dist/consts.d.ts.map +1 -1
  3. package/dist/consts.js +58 -4
  4. package/dist/consts.js.map +1 -1
  5. package/dist/handy.d.ts +2 -0
  6. package/dist/handy.d.ts.map +1 -1
  7. package/dist/handy.js +15 -1
  8. package/dist/handy.js.map +1 -1
  9. package/dist/mappers/ascendex.d.ts +1 -1
  10. package/dist/mappers/ascendex.d.ts.map +1 -1
  11. package/dist/mappers/ascendex.js +5 -0
  12. package/dist/mappers/ascendex.js.map +1 -1
  13. package/dist/mappers/binance.d.ts +1 -1
  14. package/dist/mappers/binance.d.ts.map +1 -1
  15. package/dist/mappers/binance.js +5 -11
  16. package/dist/mappers/binance.js.map +1 -1
  17. package/dist/mappers/binancedex.d.ts +1 -1
  18. package/dist/mappers/binancedex.d.ts.map +1 -1
  19. package/dist/mappers/binancedex.js +4 -0
  20. package/dist/mappers/binancedex.js.map +1 -1
  21. package/dist/mappers/binanceoptions.d.ts.map +1 -1
  22. package/dist/mappers/binanceoptions.js +3 -0
  23. package/dist/mappers/binanceoptions.js.map +1 -1
  24. package/dist/mappers/bitfinex.d.ts +1 -1
  25. package/dist/mappers/bitfinex.d.ts.map +1 -1
  26. package/dist/mappers/bitfinex.js +5 -0
  27. package/dist/mappers/bitfinex.js.map +1 -1
  28. package/dist/mappers/bitflyer.d.ts +1 -1
  29. package/dist/mappers/bitflyer.d.ts.map +1 -1
  30. package/dist/mappers/bitflyer.js +3 -0
  31. package/dist/mappers/bitflyer.js.map +1 -1
  32. package/dist/mappers/bitmex.d.ts +1 -1
  33. package/dist/mappers/bitmex.d.ts.map +1 -1
  34. package/dist/mappers/bitmex.js +5 -0
  35. package/dist/mappers/bitmex.js.map +1 -1
  36. package/dist/mappers/bitstamp.d.ts.map +1 -1
  37. package/dist/mappers/bitstamp.js +3 -8
  38. package/dist/mappers/bitstamp.js.map +1 -1
  39. package/dist/mappers/bybit.d.ts.map +1 -1
  40. package/dist/mappers/bybit.js +5 -0
  41. package/dist/mappers/bybit.js.map +1 -1
  42. package/dist/mappers/coinbase.d.ts.map +1 -1
  43. package/dist/mappers/coinbase.js +3 -0
  44. package/dist/mappers/coinbase.js.map +1 -1
  45. package/dist/mappers/coinflex.d.ts +1 -1
  46. package/dist/mappers/coinflex.d.ts.map +1 -1
  47. package/dist/mappers/coinflex.js +4 -0
  48. package/dist/mappers/coinflex.js.map +1 -1
  49. package/dist/mappers/cryptofacilities.d.ts +1 -1
  50. package/dist/mappers/cryptofacilities.d.ts.map +1 -1
  51. package/dist/mappers/cryptofacilities.js +6 -0
  52. package/dist/mappers/cryptofacilities.js.map +1 -1
  53. package/dist/mappers/delta.d.ts +1 -1
  54. package/dist/mappers/delta.d.ts.map +1 -1
  55. package/dist/mappers/delta.js +4 -0
  56. package/dist/mappers/delta.js.map +1 -1
  57. package/dist/mappers/deribit.d.ts +1 -1
  58. package/dist/mappers/deribit.d.ts.map +1 -1
  59. package/dist/mappers/deribit.js +6 -0
  60. package/dist/mappers/deribit.js.map +1 -1
  61. package/dist/mappers/dydx.d.ts +1 -1
  62. package/dist/mappers/dydx.d.ts.map +1 -1
  63. package/dist/mappers/dydx.js +4 -0
  64. package/dist/mappers/dydx.js.map +1 -1
  65. package/dist/mappers/ftx.d.ts +1 -1
  66. package/dist/mappers/ftx.d.ts.map +1 -1
  67. package/dist/mappers/ftx.js +5 -0
  68. package/dist/mappers/ftx.js.map +1 -1
  69. package/dist/mappers/gateio.d.ts.map +1 -1
  70. package/dist/mappers/gateio.js +3 -0
  71. package/dist/mappers/gateio.js.map +1 -1
  72. package/dist/mappers/gateiofutures.d.ts +1 -1
  73. package/dist/mappers/gateiofutures.d.ts.map +1 -1
  74. package/dist/mappers/gateiofutures.js +4 -0
  75. package/dist/mappers/gateiofutures.js.map +1 -1
  76. package/dist/mappers/gemini.d.ts.map +1 -1
  77. package/dist/mappers/gemini.js +3 -0
  78. package/dist/mappers/gemini.js.map +1 -1
  79. package/dist/mappers/hitbtc.d.ts.map +1 -1
  80. package/dist/mappers/hitbtc.js +3 -0
  81. package/dist/mappers/hitbtc.js.map +1 -1
  82. package/dist/mappers/huobi.d.ts +2 -2
  83. package/dist/mappers/huobi.d.ts.map +1 -1
  84. package/dist/mappers/huobi.js +3 -1
  85. package/dist/mappers/huobi.js.map +1 -1
  86. package/dist/mappers/index.d.ts +3 -3
  87. package/dist/mappers/index.d.ts.map +1 -1
  88. package/dist/mappers/index.js +43 -23
  89. package/dist/mappers/index.js.map +1 -1
  90. package/dist/mappers/kraken.d.ts.map +1 -1
  91. package/dist/mappers/kraken.js +3 -0
  92. package/dist/mappers/kraken.js.map +1 -1
  93. package/dist/mappers/okex.d.ts +247 -1
  94. package/dist/mappers/okex.d.ts.map +1 -1
  95. package/dist/mappers/okex.js +399 -1
  96. package/dist/mappers/okex.js.map +1 -1
  97. package/dist/mappers/poloniex.d.ts.map +1 -1
  98. package/dist/mappers/poloniex.js +3 -0
  99. package/dist/mappers/poloniex.js.map +1 -1
  100. package/dist/mappers/serum.d.ts +1 -1
  101. package/dist/mappers/serum.d.ts.map +1 -1
  102. package/dist/mappers/serum.js +9 -0
  103. package/dist/mappers/serum.js.map +1 -1
  104. package/dist/mappers/upbit.d.ts +1 -1
  105. package/dist/mappers/upbit.d.ts.map +1 -1
  106. package/dist/mappers/upbit.js +3 -0
  107. package/dist/mappers/upbit.js.map +1 -1
  108. package/dist/realtimefeeds/okex.d.ts +4 -2
  109. package/dist/realtimefeeds/okex.d.ts.map +1 -1
  110. package/dist/realtimefeeds/okex.js +38 -10
  111. package/dist/realtimefeeds/okex.js.map +1 -1
  112. package/package.json +1 -1
  113. package/src/consts.ts +62 -4
  114. package/src/handy.ts +14 -0
  115. package/src/mappers/ascendex.ts +6 -1
  116. package/src/mappers/binance.ts +2 -9
  117. package/src/mappers/binancedex.ts +6 -1
  118. package/src/mappers/binanceoptions.ts +7 -1
  119. package/src/mappers/bitfinex.ts +10 -1
  120. package/src/mappers/bitflyer.ts +8 -2
  121. package/src/mappers/bitmex.ts +12 -2
  122. package/src/mappers/bitstamp.ts +1 -7
  123. package/src/mappers/bybit.ts +9 -0
  124. package/src/mappers/coinbase.ts +7 -1
  125. package/src/mappers/coinflex.ts +8 -1
  126. package/src/mappers/cryptofacilities.ts +12 -1
  127. package/src/mappers/delta.ts +8 -1
  128. package/src/mappers/deribit.ts +14 -2
  129. package/src/mappers/dydx.ts +8 -1
  130. package/src/mappers/ftx.ts +12 -2
  131. package/src/mappers/gateio.ts +5 -0
  132. package/src/mappers/gateiofutures.ts +8 -1
  133. package/src/mappers/gemini.ts +5 -0
  134. package/src/mappers/hitbtc.ts +5 -0
  135. package/src/mappers/huobi.ts +6 -2
  136. package/src/mappers/index.ts +77 -24
  137. package/src/mappers/kraken.ts +7 -1
  138. package/src/mappers/okex.ts +596 -2
  139. package/src/mappers/poloniex.ts +5 -0
  140. package/src/mappers/serum.ts +14 -2
  141. package/src/mappers/upbit.ts +6 -1
  142. package/src/realtimefeeds/okex.ts +42 -10
@@ -1,7 +1,589 @@
1
- import { asNumberIfValid } from '../handy'
2
- import { BookChange, DerivativeTicker, Exchange, Trade, OptionSummary, Liquidation, BookTicker } from '../types'
1
+ import { asNumberIfValid, upperCaseSymbols } from '../handy'
2
+ import { BookChange, BookTicker, DerivativeTicker, Exchange, Liquidation, OptionSummary, Trade } from '../types'
3
3
  import { Mapper, PendingTickerInfoHelper } from './mapper'
4
4
 
5
+ // V5 Okex API mappers
6
+ // https://www.okex.com/docs-v5/en/#websocket-api-public-channel-trades-channel
7
+
8
+ export class OkexV5TradesMapper implements Mapper<OKEX_EXCHANGES, Trade> {
9
+ constructor(private readonly _exchange: Exchange) {}
10
+
11
+ canHandle(message: any) {
12
+ if (message.event !== undefined || message.arg === undefined) {
13
+ return false
14
+ }
15
+ return message.arg.channel === 'trades'
16
+ }
17
+
18
+ getFilters(symbols?: string[]) {
19
+ symbols = upperCaseSymbols(symbols)
20
+
21
+ return [
22
+ {
23
+ channel: `trades` as const,
24
+ symbols
25
+ }
26
+ ]
27
+ }
28
+
29
+ *map(okexTradesMessage: OkexV5TradeMessage, localTimestamp: Date): IterableIterator<Trade> {
30
+ for (const okexTrade of okexTradesMessage.data) {
31
+ yield {
32
+ type: 'trade',
33
+ symbol: okexTrade.instId,
34
+ exchange: this._exchange,
35
+ id: okexTrade.tradeId,
36
+ price: Number(okexTrade.px),
37
+ amount: Number(okexTrade.sz),
38
+ side: okexTrade.side === 'buy' ? 'buy' : 'sell',
39
+ timestamp: new Date(Number(okexTrade.ts)),
40
+ localTimestamp: localTimestamp
41
+ }
42
+ }
43
+ }
44
+ }
45
+
46
+ const mapV5BookLevel = (level: OkexV5BookLevel) => {
47
+ const price = Number(level[0])
48
+ const amount = Number(level[1])
49
+
50
+ return { price, amount }
51
+ }
52
+
53
+ export class OkexV5BookChangeMapper implements Mapper<OKEX_EXCHANGES, BookChange> {
54
+ constructor(private readonly _exchange: Exchange) {}
55
+
56
+ canHandle(message: any) {
57
+ if (message.event !== undefined || message.arg === undefined) {
58
+ return false
59
+ }
60
+ return message.arg.channel === 'books-l2-tbt'
61
+ }
62
+
63
+ getFilters(symbols?: string[]) {
64
+ symbols = upperCaseSymbols(symbols)
65
+
66
+ return [
67
+ {
68
+ channel: `books-l2-tbt` as const,
69
+ symbols
70
+ }
71
+ ]
72
+ }
73
+
74
+ *map(okexDepthDataMessage: OkexV5BookMessage, localTimestamp: Date): IterableIterator<BookChange> {
75
+ for (const message of okexDepthDataMessage.data) {
76
+ if (okexDepthDataMessage.action === 'update' && message.bids.length === 0 && message.asks.length === 0) {
77
+ continue
78
+ }
79
+
80
+ const timestamp = new Date(Number(message.ts))
81
+
82
+ if (timestamp.valueOf() === 0) {
83
+ continue
84
+ }
85
+
86
+ yield {
87
+ type: 'book_change',
88
+ symbol: okexDepthDataMessage.arg.instId,
89
+ exchange: this._exchange,
90
+ isSnapshot: okexDepthDataMessage.action === 'snapshot',
91
+ bids: message.bids.map(mapV5BookLevel),
92
+ asks: message.asks.map(mapV5BookLevel),
93
+ timestamp,
94
+ localTimestamp: localTimestamp
95
+ }
96
+ }
97
+ }
98
+ }
99
+
100
+ export class OkexV5BookTickerMapper implements Mapper<OKEX_EXCHANGES, BookTicker> {
101
+ constructor(private readonly _exchange: Exchange) {}
102
+
103
+ canHandle(message: any) {
104
+ if (message.event !== undefined || message.arg === undefined) {
105
+ return false
106
+ }
107
+ return message.arg.channel === 'tickers'
108
+ }
109
+
110
+ getFilters(symbols?: string[]) {
111
+ symbols = upperCaseSymbols(symbols)
112
+
113
+ return [
114
+ {
115
+ channel: `tickers` as const,
116
+ symbols
117
+ }
118
+ ]
119
+ }
120
+
121
+ *map(message: OkexV5TickerMessage, localTimestamp: Date): IterableIterator<BookTicker> {
122
+ for (const okexTicker of message.data) {
123
+ const ticker: BookTicker = {
124
+ type: 'book_ticker',
125
+ symbol: okexTicker.instId,
126
+ exchange: this._exchange,
127
+
128
+ askAmount: asNumberIfValid(okexTicker.askSz),
129
+ askPrice: asNumberIfValid(okexTicker.askPx),
130
+
131
+ bidPrice: asNumberIfValid(okexTicker.bidPx),
132
+ bidAmount: asNumberIfValid(okexTicker.bidSz),
133
+ timestamp: new Date(Number(okexTicker.ts)),
134
+ localTimestamp: localTimestamp
135
+ }
136
+
137
+ yield ticker
138
+ }
139
+ }
140
+ }
141
+
142
+ export class OkexV5DerivativeTickerMapper implements Mapper<'okex-futures' | 'okex-swap', DerivativeTicker> {
143
+ private readonly pendingTickerInfoHelper = new PendingTickerInfoHelper()
144
+ private readonly _indexPrices = new Map<string, number>()
145
+
146
+ private _futuresChannels = ['tickers', 'open-interest', 'mark-price', 'index-tickers'] as const
147
+
148
+ private _swapChannels = ['tickers', 'open-interest', 'mark-price', 'index-tickers', 'funding-rate'] as const
149
+
150
+ constructor(private readonly _exchange: Exchange) {}
151
+
152
+ canHandle(message: any) {
153
+ const channels = this._exchange === 'okex-futures' ? this._futuresChannels : this._swapChannels
154
+
155
+ if (message.event !== undefined || message.arg === undefined) {
156
+ return false
157
+ }
158
+
159
+ return channels.includes(message.arg.channel)
160
+ }
161
+
162
+ getFilters(symbols?: string[]) {
163
+ symbols = upperCaseSymbols(symbols)
164
+
165
+ const channels = this._exchange === 'okex-futures' ? this._futuresChannels : this._swapChannels
166
+ return channels.map((channel) => {
167
+ if (channel === 'index-tickers') {
168
+ const indexes =
169
+ symbols !== undefined
170
+ ? symbols.map((s) => {
171
+ const symbolParts = s.split('-')
172
+ return `${symbolParts[0]}-${symbolParts[1]}`
173
+ })
174
+ : undefined
175
+ return {
176
+ channel,
177
+ symbols: indexes
178
+ }
179
+ }
180
+
181
+ return {
182
+ channel,
183
+ symbols
184
+ }
185
+ })
186
+ }
187
+
188
+ *map(
189
+ message: OkexV5TickerMessage | OkexV5OpenInterestMessage | OkexV5MarkPriceMessage | OkexV5IndexTickerMessage | OkexV5FundingRateMessage,
190
+ localTimestamp: Date
191
+ ): IterableIterator<DerivativeTicker> {
192
+ if (message.arg.channel === 'index-tickers') {
193
+ for (const dataMessage of message.data) {
194
+ const indexTickerMessage = dataMessage as OkexV5IndexTickerMessage['data'][0]
195
+
196
+ const lastIndexPrice = Number(indexTickerMessage.idxPx)
197
+ if (lastIndexPrice > 0) {
198
+ this._indexPrices.set(indexTickerMessage.instId, lastIndexPrice)
199
+ }
200
+ }
201
+
202
+ return
203
+ }
204
+
205
+ for (const dataMessage of message.data) {
206
+ const pendingTickerInfo = this.pendingTickerInfoHelper.getPendingTickerInfo(dataMessage.instId, this._exchange)
207
+ const symbolParts = dataMessage.instId.split('-')
208
+ const indexSymbol = `${symbolParts[0]}-${symbolParts[1]}`
209
+
210
+ const indexPrice = this._indexPrices.get(indexSymbol)
211
+
212
+ if (indexPrice !== undefined) {
213
+ pendingTickerInfo.updateIndexPrice(indexPrice)
214
+ }
215
+
216
+ if (message.arg.channel === 'mark-price') {
217
+ const markPriceMessage = dataMessage as OkexV5MarkPriceMessage['data'][0]
218
+
219
+ const markPrice = Number(markPriceMessage.markPx)
220
+ if (markPrice > 0) {
221
+ pendingTickerInfo.updateMarkPrice(markPrice)
222
+ pendingTickerInfo.updateTimestamp(new Date(Number(markPriceMessage.ts)))
223
+ }
224
+ }
225
+
226
+ if (message.arg.channel === 'open-interest') {
227
+ const openInterestMessage = dataMessage as OkexV5OpenInterestMessage['data'][0]
228
+
229
+ const openInterest = Number(openInterestMessage.oi)
230
+ if (openInterest > 0) {
231
+ pendingTickerInfo.updateOpenInterest(openInterest)
232
+ pendingTickerInfo.updateTimestamp(new Date(Number(openInterestMessage.ts)))
233
+ }
234
+ }
235
+
236
+ if (message.arg.channel === 'funding-rate') {
237
+ const fundingRateMessage = dataMessage as OkexV5FundingRateMessage['data'][0]
238
+
239
+ if (fundingRateMessage.fundingRate !== undefined) {
240
+ pendingTickerInfo.updateFundingRate(Number(fundingRateMessage.fundingRate))
241
+ }
242
+ if (fundingRateMessage.fundingTime !== undefined) {
243
+ pendingTickerInfo.updateFundingTimestamp(new Date(Number(fundingRateMessage.fundingTime)))
244
+ }
245
+
246
+ if (fundingRateMessage.nextFundingRate !== undefined) {
247
+ pendingTickerInfo.updatePredictedFundingRate(Number(fundingRateMessage.nextFundingRate))
248
+ }
249
+ }
250
+
251
+ if (message.arg.channel === 'tickers') {
252
+ const tickerMessage = dataMessage as OkexV5TickerMessage['data'][0]
253
+
254
+ const lastPrice = Number(tickerMessage.last)
255
+
256
+ if (lastPrice > 0) {
257
+ pendingTickerInfo.updateLastPrice(lastPrice)
258
+ pendingTickerInfo.updateTimestamp(new Date(Number(tickerMessage.ts)))
259
+ }
260
+ }
261
+
262
+ if (pendingTickerInfo.hasChanged()) {
263
+ yield pendingTickerInfo.getSnapshot(localTimestamp)
264
+ }
265
+ }
266
+ }
267
+ }
268
+
269
+ export class OkexV5LiquidationsMapper implements Mapper<OKEX_EXCHANGES, Liquidation> {
270
+ constructor(private readonly _exchange: Exchange) {}
271
+
272
+ canHandle(message: any) {
273
+ if (message.event !== undefined || message.arg === undefined) {
274
+ return false
275
+ }
276
+ return message.arg.channel === 'liquidations'
277
+ }
278
+
279
+ getFilters(symbols?: string[]) {
280
+ symbols = upperCaseSymbols(symbols)
281
+
282
+ return [
283
+ {
284
+ channel: 'liquidations',
285
+ symbols
286
+ } as any
287
+ ]
288
+ }
289
+
290
+ *map(okexLiquidationMessage: OkexV5LiquidationMessage, localTimestamp: Date): IterableIterator<Liquidation> {
291
+ for (const okexLiquidation of okexLiquidationMessage.data) {
292
+ const liquidation: Liquidation = {
293
+ type: 'liquidation',
294
+ symbol: okexLiquidationMessage.arg.instId,
295
+ exchange: this._exchange,
296
+ id: undefined,
297
+ price: Number(okexLiquidation.bkPx),
298
+ amount: Number(okexLiquidation.sz),
299
+ side: okexLiquidation.side === 'buy' ? 'buy' : 'sell',
300
+ timestamp: new Date(Number(okexLiquidation.ts)),
301
+ localTimestamp: localTimestamp
302
+ }
303
+ yield liquidation
304
+ }
305
+ }
306
+ }
307
+
308
+ export class OkexV5OptionSummaryMapper implements Mapper<'okex-options', OptionSummary> {
309
+ private readonly _indexPrices = new Map<string, number>()
310
+ private readonly _openInterests = new Map<string, number>()
311
+ private readonly _markPrices = new Map<string, number>()
312
+
313
+ private readonly _tickers = new Map<string, OkexV5TickerMessage['data'][0]>()
314
+ private readonly expiration_regex = /(\d{2})(\d{2})(\d{2})/
315
+
316
+ canHandle(message: any) {
317
+ if (message.event !== undefined || message.arg === undefined) {
318
+ return false
319
+ }
320
+ return (
321
+ message.arg.channel === 'opt-summary' ||
322
+ message.arg.channel === 'index-tickers' ||
323
+ message.arg.channel === 'tickers' ||
324
+ message.arg.channel === 'open-interest' ||
325
+ message.arg.channel === 'mark-price'
326
+ )
327
+ }
328
+
329
+ getFilters(symbols?: string[]) {
330
+ symbols = upperCaseSymbols(symbols)
331
+
332
+ const indexes =
333
+ symbols !== undefined
334
+ ? symbols.map((s) => {
335
+ const symbolParts = s.split('-')
336
+ return `${symbolParts[0]}-${symbolParts[1]}`
337
+ })
338
+ : undefined
339
+
340
+ return [
341
+ {
342
+ channel: `opt-summary`,
343
+ symbols: [] as string[]
344
+ } as const,
345
+ {
346
+ channel: `index-tickers`,
347
+ symbols: indexes
348
+ } as const,
349
+ {
350
+ channel: `tickers`,
351
+ symbols: symbols
352
+ } as const,
353
+ {
354
+ channel: `open-interest`,
355
+ symbols: symbols
356
+ } as const,
357
+ {
358
+ channel: `mark-price`,
359
+ symbols: symbols
360
+ } as const
361
+ ]
362
+ }
363
+
364
+ *map(
365
+ message: OkexV5SummaryMessage | OkexV5IndexTickerMessage | OkexV5TickerMessage | OkexV5OpenInterestMessage | OkexV5MarkPriceMessage,
366
+ localTimestamp: Date
367
+ ): IterableIterator<OptionSummary> | undefined {
368
+ if (message.arg.channel === 'index-tickers') {
369
+ for (const dataMessage of message.data) {
370
+ const indexTickerMessage = dataMessage as OkexV5IndexTickerMessage['data'][0]
371
+
372
+ const lastIndexPrice = asNumberIfValid(indexTickerMessage.idxPx)
373
+ if (lastIndexPrice !== undefined) {
374
+ this._indexPrices.set(indexTickerMessage.instId, lastIndexPrice)
375
+ }
376
+ }
377
+ return
378
+ }
379
+
380
+ if (message.arg.channel === 'open-interest') {
381
+ for (const dataMessage of message.data) {
382
+ const openInterestMessage = dataMessage as OkexV5OpenInterestMessage['data'][0]
383
+
384
+ const openInterestValue = asNumberIfValid(openInterestMessage.oi)
385
+ if (openInterestValue !== undefined) {
386
+ this._openInterests.set(openInterestMessage.instId, openInterestValue)
387
+ }
388
+ }
389
+ return
390
+ }
391
+
392
+ if (message.arg.channel === 'mark-price') {
393
+ for (const dataMessage of message.data) {
394
+ const markPriceMessage = dataMessage as OkexV5MarkPriceMessage['data'][0]
395
+
396
+ const markPrice = asNumberIfValid(markPriceMessage.markPx)
397
+ if (markPrice !== undefined) {
398
+ this._markPrices.set(markPriceMessage.instId, markPrice)
399
+ }
400
+ }
401
+ return
402
+ }
403
+
404
+ if (message.arg.channel === 'tickers') {
405
+ for (const dataMessage of message.data) {
406
+ const tickerMessage = dataMessage as OkexV5TickerMessage['data'][0]
407
+
408
+ this._tickers.set(tickerMessage.instId, tickerMessage)
409
+ }
410
+ return
411
+ }
412
+
413
+ if (message.arg.channel === 'opt-summary') {
414
+ for (const dataMessage of message.data) {
415
+ const summary = dataMessage as OkexV5SummaryMessage['data'][0]
416
+
417
+ const symbolParts = summary.instId.split('-')
418
+ const isPut = symbolParts[4] === 'P'
419
+ const strikePrice = Number(symbolParts[3])
420
+
421
+ var dateArray = this.expiration_regex.exec(symbolParts[2])!
422
+
423
+ const expirationDate = new Date(Date.UTC(+('20' + dateArray[1]), +dateArray[2] - 1, +dateArray[3], 8, 0, 0, 0))
424
+ const lastUnderlyingPrice = this._indexPrices.get(summary.uly)
425
+
426
+ const lastOpenInterest = this._openInterests.get(summary.instId)
427
+
428
+ const lastMarkPrice = this._markPrices.get(summary.instId)
429
+
430
+ const lastTickerInfo = this._tickers.get(summary.instId)
431
+
432
+ const optionSummary: OptionSummary = {
433
+ type: 'option_summary',
434
+ symbol: summary.instId,
435
+ exchange: 'okex-options',
436
+ optionType: isPut ? 'put' : 'call',
437
+ strikePrice,
438
+ expirationDate,
439
+
440
+ bestBidPrice: lastTickerInfo !== undefined ? asNumberIfValid(lastTickerInfo.bidPx) : undefined,
441
+ bestBidAmount: lastTickerInfo !== undefined ? asNumberIfValid(lastTickerInfo.bidSz) : undefined,
442
+ bestBidIV: asNumberIfValid(summary.bidVol),
443
+
444
+ bestAskPrice: lastTickerInfo !== undefined ? asNumberIfValid(lastTickerInfo.askPx) : undefined,
445
+ bestAskAmount: lastTickerInfo !== undefined ? asNumberIfValid(lastTickerInfo.askSz) : undefined,
446
+ bestAskIV: asNumberIfValid(summary.askVol),
447
+
448
+ lastPrice: lastTickerInfo !== undefined ? asNumberIfValid(lastTickerInfo.last) : undefined,
449
+ openInterest: lastOpenInterest,
450
+
451
+ markPrice: lastMarkPrice,
452
+ markIV: asNumberIfValid(summary.markVol),
453
+
454
+ delta: asNumberIfValid(summary.delta),
455
+ gamma: asNumberIfValid(summary.gamma),
456
+ vega: asNumberIfValid(summary.vega),
457
+ theta: asNumberIfValid(summary.theta),
458
+ rho: undefined,
459
+
460
+ underlyingPrice: lastUnderlyingPrice,
461
+ underlyingIndex: summary.uly,
462
+
463
+ timestamp: new Date(Number(summary.ts)),
464
+ localTimestamp: localTimestamp
465
+ }
466
+
467
+ yield optionSummary
468
+ }
469
+ }
470
+ }
471
+ }
472
+
473
+ type OkexV5TradeMessage = {
474
+ arg: { channel: 'trades'; instId: 'CRV-USDT' }
475
+ data: [{ instId: 'CRV-USDT'; tradeId: '21300150'; px: '3.973'; sz: '13.491146'; side: 'buy'; ts: '1639999319938' }]
476
+ }
477
+
478
+ type OkexV5BookLevel = [string, string, string, string]
479
+
480
+ type OkexV5BookMessage =
481
+ | {
482
+ arg: { channel: 'books-l2-tbt'; instId: string }
483
+ action: 'snapshot'
484
+ data: [
485
+ {
486
+ asks: OkexV5BookLevel[]
487
+ bids: OkexV5BookLevel[]
488
+ ts: string
489
+ }
490
+ ]
491
+ }
492
+ | {
493
+ arg: { channel: 'books-l2-tbt'; instId: string }
494
+ action: 'update'
495
+ data: [{ asks: OkexV5BookLevel[]; bids: OkexV5BookLevel[]; ts: string }]
496
+ }
497
+
498
+ type OkexV5TickerMessage = {
499
+ arg: { channel: 'tickers'; instId: string }
500
+ data: [
501
+ {
502
+ instType: 'SPOT'
503
+ instId: 'ACT-USDT'
504
+ last: '0.00718'
505
+ lastSz: '8052.117146'
506
+ askPx: '0.0072'
507
+ askSz: '54969.407534'
508
+ bidPx: '0.00713'
509
+ bidSz: '4092.326'
510
+ open24h: '0.00717'
511
+ high24h: '0.00722'
512
+ low24h: '0.00696'
513
+ sodUtc0: '0.00714'
514
+ sodUtc8: '0.00721'
515
+ volCcy24h: '278377.765301'
516
+ vol24h: '39168761.49997'
517
+ ts: '1639999318686'
518
+ }
519
+ ]
520
+ }
521
+
522
+ type OkexV5OpenInterestMessage = {
523
+ arg: { channel: 'open-interest'; instId: string }
524
+ data: [{ instId: 'FIL-USDT-220325'; instType: 'FUTURES'; oi: '236870'; oiCcy: '23687'; ts: '1640131202886' }]
525
+ }
526
+
527
+ type OkexV5MarkPriceMessage = {
528
+ arg: { channel: 'mark-price'; instId: string }
529
+ data: [{ instId: 'FIL-USDT-220325'; instType: 'FUTURES'; markPx: '36.232'; ts: '1640131204676' }]
530
+ }
531
+
532
+ type OkexV5IndexTickerMessage = {
533
+ arg: { channel: 'index-tickers'; instId: string }
534
+ data: [
535
+ {
536
+ instId: 'FIL-USDT'
537
+ idxPx: '35.583'
538
+ open24h: '34.558'
539
+ high24h: '35.862'
540
+ low24h: '34.529'
541
+ sodUtc0: '35.309'
542
+ sodUtc8: '34.83'
543
+ ts: '1640140200581'
544
+ }
545
+ ]
546
+ }
547
+
548
+ type OkexV5FundingRateMessage = {
549
+ arg: { channel: 'funding-rate'; instId: string }
550
+ data: [
551
+ { fundingRate: '0.00048105' | undefined; fundingTime: '1640131200000'; instId: string; instType: 'SWAP'; nextFundingRate: '0.00114' }
552
+ ]
553
+ }
554
+
555
+ type OkexV5LiquidationMessage = {
556
+ arg: { channel: 'liquidations'; instId: 'BTC-USDT-211231'; generated: true }
557
+ data: [{ bkLoss: '0'; bkPx: '49674.2'; ccy: ''; posSide: 'short'; side: 'buy'; sz: '40'; ts: '1640140211925' }]
558
+ }
559
+
560
+ type OkexV5SummaryMessage = {
561
+ arg: { channel: 'opt-summary'; uly: 'ETH-USD' }
562
+ data: [
563
+ {
564
+ instType: 'OPTION'
565
+ instId: 'ETH-USD-211222-4000-C'
566
+ uly: 'ETH-USD'
567
+ delta: '0.1975745164'
568
+ gamma: '4.7290833601'
569
+ vega: '0.0002005415'
570
+ theta: '-0.004262964'
571
+ lever: '162.472613953'
572
+ markVol: '0.7794507758'
573
+ bidVol: '0.7421960156'
574
+ askVol: '0.8203208593'
575
+ realVol: ''
576
+ deltaBS: '0.2038286081'
577
+ gammaBS: '0.0013437829'
578
+ thetaBS: '-16.4798150221'
579
+ vegaBS: '0.7647227087'
580
+ ts: '1640001659301'
581
+ }
582
+ ]
583
+ }
584
+
585
+ //---
586
+ //V3 Okex API mappers
5
587
  // https://www.okex.com/docs/en/#ws_swap-README
6
588
 
7
589
  export class OkexTradesMapper implements Mapper<OKEX_EXCHANGES, Trade> {
@@ -12,6 +594,8 @@ export class OkexTradesMapper implements Mapper<OKEX_EXCHANGES, Trade> {
12
594
  }
13
595
 
14
596
  getFilters(symbols?: string[]) {
597
+ symbols = upperCaseSymbols(symbols)
598
+
15
599
  return [
16
600
  {
17
601
  channel: `${this._market}/trade` as const,
@@ -60,6 +644,8 @@ export class OkexBookChangeMapper implements Mapper<OKEX_EXCHANGES, BookChange>
60
644
  }
61
645
 
62
646
  getFilters(symbols?: string[]) {
647
+ symbols = upperCaseSymbols(symbols)
648
+
63
649
  if (this._canUseTickByTickChannel) {
64
650
  return [
65
651
  {
@@ -124,6 +710,8 @@ export class OkexDerivativeTickerMapper implements Mapper<'okex-futures' | 'okex
124
710
  }
125
711
 
126
712
  getFilters(symbols?: string[]) {
713
+ symbols = upperCaseSymbols(symbols)
714
+
127
715
  const channels = this._exchange === 'okex-futures' ? this._futuresChannels : this._swapChannels
128
716
  return channels.map((channel) => {
129
717
  return {
@@ -180,6 +768,8 @@ export class OkexOptionSummaryMapper implements Mapper<'okex-options', OptionSum
180
768
  }
181
769
 
182
770
  getFilters(symbols?: string[]) {
771
+ symbols = upperCaseSymbols(symbols)
772
+
183
773
  const indexes =
184
774
  symbols !== undefined
185
775
  ? symbols.map((s) => {
@@ -269,6 +859,8 @@ export class OkexLiquidationsMapper implements Mapper<OKEX_EXCHANGES, Liquidatio
269
859
  }
270
860
 
271
861
  getFilters(symbols?: string[]) {
862
+ symbols = upperCaseSymbols(symbols)
863
+
272
864
  return [
273
865
  {
274
866
  channel: `${this._market}/liquidation`,
@@ -303,6 +895,8 @@ export class OkexBookTickerMapper implements Mapper<OKEX_EXCHANGES, BookTicker>
303
895
  }
304
896
 
305
897
  getFilters(symbols?: string[]) {
898
+ symbols = upperCaseSymbols(symbols)
899
+
306
900
  return [
307
901
  {
308
902
  channel: `${this._market}/ticker`,
@@ -1,3 +1,4 @@
1
+ import { upperCaseSymbols } from '../handy'
1
2
  import { BookChange, Trade } from '../types'
2
3
  import { Mapper } from './mapper'
3
4
 
@@ -19,6 +20,8 @@ export class PoloniexTradesMapper implements Mapper<'poloniex', Trade> {
19
20
  }
20
21
 
21
22
  getFilters(symbols?: string[]) {
23
+ symbols = upperCaseSymbols(symbols)
24
+
22
25
  return [
23
26
  {
24
27
  channel: 'price_aggregated_book',
@@ -89,6 +92,8 @@ export class PoloniexBookChangeMapper implements Mapper<'poloniex', BookChange>
89
92
  }
90
93
 
91
94
  getFilters(symbols?: string[]) {
95
+ symbols = upperCaseSymbols(symbols)
96
+
92
97
  return [
93
98
  {
94
99
  channel: 'price_aggregated_book',
@@ -1,6 +1,6 @@
1
+ import { asNumberIfValid, upperCaseSymbols } from '../handy'
2
+ import { BookChange, BookTicker, Exchange, Trade } from '../types'
1
3
  import { Mapper } from './mapper'
2
- import { Trade, BookChange, BookTicker, Exchange } from '../types'
3
- import { asNumberIfValid } from '../handy'
4
4
 
5
5
  export class SerumTradesMapper implements Mapper<'serum' | 'star-atlas', Trade> {
6
6
  constructor(private readonly _exchange: Exchange) {}
@@ -10,6 +10,10 @@ export class SerumTradesMapper implements Mapper<'serum' | 'star-atlas', Trade>
10
10
  }
11
11
 
12
12
  getFilters(symbols?: string[]) {
13
+ if (this._exchange === 'serum') {
14
+ symbols = upperCaseSymbols(symbols)
15
+ }
16
+
13
17
  return [
14
18
  {
15
19
  channel: 'trade',
@@ -41,6 +45,10 @@ export class SerumBookChangeMapper implements Mapper<'serum' | 'star-atlas', Boo
41
45
  }
42
46
 
43
47
  getFilters(symbols?: string[]) {
48
+ if (this._exchange === 'serum') {
49
+ symbols = upperCaseSymbols(symbols)
50
+ }
51
+
44
52
  return [
45
53
  {
46
54
  channel: 'l2snapshot',
@@ -81,6 +89,10 @@ export class SerumBookTickerMapper implements Mapper<'serum' | 'star-atlas', Boo
81
89
  }
82
90
 
83
91
  getFilters(symbols?: string[]) {
92
+ if (this._exchange === 'serum') {
93
+ symbols = upperCaseSymbols(symbols)
94
+ }
95
+
84
96
  return [
85
97
  {
86
98
  channel: 'quote',