tardis-dev 12.6.2 → 12.6.7

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 (90) hide show
  1. package/dist/apikeyaccessinfo.js +1 -1
  2. package/dist/apikeyaccessinfo.js.map +1 -1
  3. package/dist/clearcache.js +12 -12
  4. package/dist/clearcache.js.map +1 -1
  5. package/dist/combine.js +1 -1
  6. package/dist/combine.js.map +1 -1
  7. package/dist/computable/booksnapshot.d.ts.map +1 -1
  8. package/dist/computable/booksnapshot.js +1 -1
  9. package/dist/computable/booksnapshot.js.map +1 -1
  10. package/dist/computable/tradebar.d.ts.map +1 -1
  11. package/dist/computable/tradebar.js.map +1 -1
  12. package/dist/debug.js +1 -1
  13. package/dist/debug.js.map +1 -1
  14. package/dist/downloaddatasets.js +13 -13
  15. package/dist/downloaddatasets.js.map +1 -1
  16. package/dist/exchangedetails.js +1 -1
  17. package/dist/exchangedetails.js.map +1 -1
  18. package/dist/filter.js.map +1 -1
  19. package/dist/handy.js +8 -8
  20. package/dist/handy.js.map +1 -1
  21. package/dist/instrumentinfo.js +1 -1
  22. package/dist/instrumentinfo.js.map +1 -1
  23. package/dist/mappers/binance.d.ts.map +1 -1
  24. package/dist/mappers/binance.js +2 -2
  25. package/dist/mappers/binance.js.map +1 -1
  26. package/dist/mappers/binanceoptions.js +10 -10
  27. package/dist/mappers/binanceoptions.js.map +1 -1
  28. package/dist/mappers/bitflyer.js +1 -1
  29. package/dist/mappers/bitflyer.js.map +1 -1
  30. package/dist/mappers/coinbase.js +2 -2
  31. package/dist/mappers/coinbase.js.map +1 -1
  32. package/dist/mappers/ftx.js +2 -2
  33. package/dist/mappers/ftx.js.map +1 -1
  34. package/dist/mappers/huobi.d.ts.map +1 -1
  35. package/dist/mappers/huobi.js +11 -11
  36. package/dist/mappers/huobi.js.map +1 -1
  37. package/dist/mappers/okex.js +14 -14
  38. package/dist/mappers/okex.js.map +1 -1
  39. package/dist/mappers/phemex.d.ts.map +1 -1
  40. package/dist/mappers/phemex.js.map +1 -1
  41. package/dist/realtimefeeds/ascendex.js +2 -2
  42. package/dist/realtimefeeds/ascendex.js.map +1 -1
  43. package/dist/realtimefeeds/binance.js +1 -1
  44. package/dist/realtimefeeds/binance.js.map +1 -1
  45. package/dist/realtimefeeds/bitmex.js +1 -1
  46. package/dist/realtimefeeds/bitmex.js.map +1 -1
  47. package/dist/realtimefeeds/ftx.js +1 -1
  48. package/dist/realtimefeeds/ftx.js.map +1 -1
  49. package/dist/realtimefeeds/huobi.js +7 -7
  50. package/dist/realtimefeeds/huobi.js.map +1 -1
  51. package/dist/realtimefeeds/okex.js +1 -1
  52. package/dist/realtimefeeds/okex.js.map +1 -1
  53. package/dist/realtimefeeds/realtimefeed.js +9 -9
  54. package/dist/realtimefeeds/realtimefeed.js.map +1 -1
  55. package/dist/replay.d.ts.map +1 -1
  56. package/dist/replay.js +34 -36
  57. package/dist/replay.js.map +1 -1
  58. package/dist/stream.js +4 -4
  59. package/dist/stream.js.map +1 -1
  60. package/dist/worker.js +12 -12
  61. package/dist/worker.js.map +1 -1
  62. package/package.json +19 -18
  63. package/src/computable/booksnapshot.ts +4 -2
  64. package/src/computable/tradebar.ts +4 -1
  65. package/src/downloaddatasets.ts +188 -188
  66. package/src/filter.ts +69 -69
  67. package/src/instrumentinfo.ts +1 -1
  68. package/src/mappers/ascendex.ts +156 -156
  69. package/src/mappers/binance.ts +6 -3
  70. package/src/mappers/coinflex.ts +159 -159
  71. package/src/mappers/delta.ts +175 -175
  72. package/src/mappers/dydx.ts +303 -303
  73. package/src/mappers/gateio.ts +117 -117
  74. package/src/mappers/gateiofutures.ts +185 -185
  75. package/src/mappers/huobi.ts +4 -2
  76. package/src/mappers/phemex.ts +179 -177
  77. package/src/mappers/poloniex.ts +150 -150
  78. package/src/mappers/serum.ts +103 -103
  79. package/src/mappers/upbit.ts +104 -104
  80. package/src/realtimefeeds/ascendex.ts +65 -65
  81. package/src/realtimefeeds/coinflex.ts +29 -29
  82. package/src/realtimefeeds/delta.ts +27 -27
  83. package/src/realtimefeeds/dydx.ts +40 -40
  84. package/src/realtimefeeds/gateio.ts +41 -41
  85. package/src/realtimefeeds/gateiofutures.ts +90 -90
  86. package/src/realtimefeeds/poloniex.ts +28 -28
  87. package/src/realtimefeeds/realtimefeed.ts +2 -2
  88. package/src/realtimefeeds/upbit.ts +35 -35
  89. package/src/replay.ts +7 -8
  90. package/src/stream.ts +1 -1
@@ -1,177 +1,179 @@
1
- import { Mapper, PendingTickerInfoHelper } from './mapper'
2
- import { Trade, BookChange, DerivativeTicker } from '../types'
3
-
4
- // phemex provides timestamps in nanoseconds
5
- const fromNanoSecondsToDate = (nanos: number) => {
6
- const microtimestamp = Math.floor(nanos / 1000)
7
-
8
- const timestamp = new Date(microtimestamp / 1000)
9
- timestamp.μs = microtimestamp % 1000
10
-
11
- return timestamp
12
- }
13
-
14
- function getPriceScale(symbol: string) {
15
- if (symbol.startsWith('s')) {
16
- return 1e8
17
- }
18
-
19
- return 1e4
20
- }
21
-
22
- function getQtyScale(symbol: string) {
23
- if (symbol.startsWith('s')) {
24
- return 1e8
25
- }
26
-
27
- return 1
28
- }
29
-
30
- function getSymbols(symbols?: string[]) {
31
- if (symbols === undefined) {
32
- return
33
- }
34
- return symbols.map((symbol) => {
35
- if (symbol.startsWith('S')) {
36
- return symbol.charAt(0).toLowerCase() + symbol.slice(1)
37
- }
38
- return symbol
39
- })
40
- }
41
-
42
- export const phemexTradesMapper: Mapper<'phemex', Trade> = {
43
- canHandle(message: PhemexTradeMessage) {
44
- return 'trades' in message && message.type === 'incremental'
45
- },
46
-
47
- getFilters(symbols?: string[]) {
48
- return [
49
- {
50
- channel: 'trades',
51
- symbols: getSymbols(symbols)
52
- } as const
53
- ]
54
- },
55
-
56
- *map(message: PhemexTradeMessage, localTimestamp: Date): IterableIterator<Trade> {
57
- for (const [timestamp, side, priceEp, qty] of message.trades) {
58
- const symbol = message.symbol
59
-
60
- yield {
61
- type: 'trade',
62
- symbol: symbol.toUpperCase(),
63
- exchange: 'phemex',
64
- id: undefined,
65
- price: priceEp / getPriceScale(symbol),
66
- amount: qty / getQtyScale(symbol),
67
- side: side === 'Buy' ? 'buy' : 'sell',
68
- timestamp: fromNanoSecondsToDate(timestamp),
69
- localTimestamp: localTimestamp
70
- }
71
- }
72
- }
73
- }
74
-
75
- const mapBookLevelForSymbol = (symbol: string) => ([priceEp, qty]: PhemexBookLevel) => {
76
- return {
77
- price: priceEp / getPriceScale(symbol),
78
- amount: qty / getQtyScale(symbol)
79
- }
80
- }
81
-
82
- export const phemexBookChangeMapper: Mapper<'phemex', BookChange> = {
83
- canHandle(message: PhemexBookMessage) {
84
- return 'book' in message
85
- },
86
-
87
- getFilters(symbols?: string[]) {
88
- return [
89
- {
90
- channel: 'book',
91
- symbols: getSymbols(symbols)
92
- } as const
93
- ]
94
- },
95
-
96
- *map(message: PhemexBookMessage, localTimestamp: Date): IterableIterator<BookChange> {
97
- const symbol = message.symbol
98
- const mapBookLevel = mapBookLevelForSymbol(symbol)
99
- yield {
100
- type: 'book_change',
101
- symbol: symbol.toUpperCase(),
102
- exchange: 'phemex',
103
- isSnapshot: message.type === 'snapshot',
104
- bids: message.book.bids.map(mapBookLevel),
105
- asks: message.book.asks.map(mapBookLevel),
106
-
107
- timestamp: fromNanoSecondsToDate(message.timestamp),
108
- localTimestamp
109
- }
110
- }
111
- }
112
-
113
- export class PhemexDerivativeTickerMapper implements Mapper<'phemex', DerivativeTicker> {
114
- private readonly pendingTickerInfoHelper = new PendingTickerInfoHelper()
115
-
116
- canHandle(message: PhemexTicker) {
117
- return 'market24h' in message
118
- }
119
-
120
- getFilters(symbols?: string[]) {
121
- return [
122
- {
123
- channel: 'market24h',
124
- symbols
125
- } as const
126
- ]
127
- }
128
-
129
- *map(message: PhemexTicker, localTimestamp: Date): IterableIterator<DerivativeTicker> {
130
- const pendingTickerInfo = this.pendingTickerInfoHelper.getPendingTickerInfo(message.market24h.symbol, 'phemex')
131
- const phemexTicker = message.market24h
132
- pendingTickerInfo.updateFundingRate(phemexTicker.fundingRate / 100000000)
133
- pendingTickerInfo.updatePredictedFundingRate(phemexTicker.predFundingRate / 100000000)
134
- pendingTickerInfo.updateIndexPrice(phemexTicker.indexPrice / 10000)
135
- pendingTickerInfo.updateMarkPrice(phemexTicker.markPrice / 10000)
136
- pendingTickerInfo.updateOpenInterest(phemexTicker.openInterest)
137
- pendingTickerInfo.updateLastPrice(phemexTicker.close / 10000)
138
- pendingTickerInfo.updateTimestamp(fromNanoSecondsToDate(message.timestamp))
139
-
140
- if (pendingTickerInfo.hasChanged()) {
141
- yield pendingTickerInfo.getSnapshot(localTimestamp)
142
- }
143
- }
144
- }
145
-
146
- type PhemexTradeMessage = {
147
- symbol: string
148
- trades: [[number, 'Buy' | 'Sell', number, number]]
149
- type: 'incremental' | 'snapshot'
150
- }
151
-
152
- type PhemexBookLevel = [number, number]
153
-
154
- type PhemexBookMessage = {
155
- book: {
156
- asks: PhemexBookLevel[]
157
- bids: PhemexBookLevel[]
158
- }
159
-
160
- symbol: string
161
- timestamp: number
162
- type: 'incremental' | 'snapshot'
163
- }
164
-
165
- type PhemexTicker = {
166
- market24h: {
167
- fundingRate: number
168
- indexPrice: number
169
- markPrice: number
170
- openInterest: number
171
- predFundingRate: number
172
- symbol: string
173
- close: number
174
- }
175
-
176
- timestamp: number
177
- }
1
+ import { Mapper, PendingTickerInfoHelper } from './mapper'
2
+ import { Trade, BookChange, DerivativeTicker } from '../types'
3
+
4
+ // phemex provides timestamps in nanoseconds
5
+ const fromNanoSecondsToDate = (nanos: number) => {
6
+ const microtimestamp = Math.floor(nanos / 1000)
7
+
8
+ const timestamp = new Date(microtimestamp / 1000)
9
+ timestamp.μs = microtimestamp % 1000
10
+
11
+ return timestamp
12
+ }
13
+
14
+ function getPriceScale(symbol: string) {
15
+ if (symbol.startsWith('s')) {
16
+ return 1e8
17
+ }
18
+
19
+ return 1e4
20
+ }
21
+
22
+ function getQtyScale(symbol: string) {
23
+ if (symbol.startsWith('s')) {
24
+ return 1e8
25
+ }
26
+
27
+ return 1
28
+ }
29
+
30
+ function getSymbols(symbols?: string[]) {
31
+ if (symbols === undefined) {
32
+ return
33
+ }
34
+ return symbols.map((symbol) => {
35
+ if (symbol.startsWith('S')) {
36
+ return symbol.charAt(0).toLowerCase() + symbol.slice(1)
37
+ }
38
+ return symbol
39
+ })
40
+ }
41
+
42
+ export const phemexTradesMapper: Mapper<'phemex', Trade> = {
43
+ canHandle(message: PhemexTradeMessage) {
44
+ return 'trades' in message && message.type === 'incremental'
45
+ },
46
+
47
+ getFilters(symbols?: string[]) {
48
+ return [
49
+ {
50
+ channel: 'trades',
51
+ symbols: getSymbols(symbols)
52
+ } as const
53
+ ]
54
+ },
55
+
56
+ *map(message: PhemexTradeMessage, localTimestamp: Date): IterableIterator<Trade> {
57
+ for (const [timestamp, side, priceEp, qty] of message.trades) {
58
+ const symbol = message.symbol
59
+
60
+ yield {
61
+ type: 'trade',
62
+ symbol: symbol.toUpperCase(),
63
+ exchange: 'phemex',
64
+ id: undefined,
65
+ price: priceEp / getPriceScale(symbol),
66
+ amount: qty / getQtyScale(symbol),
67
+ side: side === 'Buy' ? 'buy' : 'sell',
68
+ timestamp: fromNanoSecondsToDate(timestamp),
69
+ localTimestamp: localTimestamp
70
+ }
71
+ }
72
+ }
73
+ }
74
+
75
+ const mapBookLevelForSymbol =
76
+ (symbol: string) =>
77
+ ([priceEp, qty]: PhemexBookLevel) => {
78
+ return {
79
+ price: priceEp / getPriceScale(symbol),
80
+ amount: qty / getQtyScale(symbol)
81
+ }
82
+ }
83
+
84
+ export const phemexBookChangeMapper: Mapper<'phemex', BookChange> = {
85
+ canHandle(message: PhemexBookMessage) {
86
+ return 'book' in message
87
+ },
88
+
89
+ getFilters(symbols?: string[]) {
90
+ return [
91
+ {
92
+ channel: 'book',
93
+ symbols: getSymbols(symbols)
94
+ } as const
95
+ ]
96
+ },
97
+
98
+ *map(message: PhemexBookMessage, localTimestamp: Date): IterableIterator<BookChange> {
99
+ const symbol = message.symbol
100
+ const mapBookLevel = mapBookLevelForSymbol(symbol)
101
+ yield {
102
+ type: 'book_change',
103
+ symbol: symbol.toUpperCase(),
104
+ exchange: 'phemex',
105
+ isSnapshot: message.type === 'snapshot',
106
+ bids: message.book.bids.map(mapBookLevel),
107
+ asks: message.book.asks.map(mapBookLevel),
108
+
109
+ timestamp: fromNanoSecondsToDate(message.timestamp),
110
+ localTimestamp
111
+ }
112
+ }
113
+ }
114
+
115
+ export class PhemexDerivativeTickerMapper implements Mapper<'phemex', DerivativeTicker> {
116
+ private readonly pendingTickerInfoHelper = new PendingTickerInfoHelper()
117
+
118
+ canHandle(message: PhemexTicker) {
119
+ return 'market24h' in message
120
+ }
121
+
122
+ getFilters(symbols?: string[]) {
123
+ return [
124
+ {
125
+ channel: 'market24h',
126
+ symbols
127
+ } as const
128
+ ]
129
+ }
130
+
131
+ *map(message: PhemexTicker, localTimestamp: Date): IterableIterator<DerivativeTicker> {
132
+ const pendingTickerInfo = this.pendingTickerInfoHelper.getPendingTickerInfo(message.market24h.symbol, 'phemex')
133
+ const phemexTicker = message.market24h
134
+ pendingTickerInfo.updateFundingRate(phemexTicker.fundingRate / 100000000)
135
+ pendingTickerInfo.updatePredictedFundingRate(phemexTicker.predFundingRate / 100000000)
136
+ pendingTickerInfo.updateIndexPrice(phemexTicker.indexPrice / 10000)
137
+ pendingTickerInfo.updateMarkPrice(phemexTicker.markPrice / 10000)
138
+ pendingTickerInfo.updateOpenInterest(phemexTicker.openInterest)
139
+ pendingTickerInfo.updateLastPrice(phemexTicker.close / 10000)
140
+ pendingTickerInfo.updateTimestamp(fromNanoSecondsToDate(message.timestamp))
141
+
142
+ if (pendingTickerInfo.hasChanged()) {
143
+ yield pendingTickerInfo.getSnapshot(localTimestamp)
144
+ }
145
+ }
146
+ }
147
+
148
+ type PhemexTradeMessage = {
149
+ symbol: string
150
+ trades: [[number, 'Buy' | 'Sell', number, number]]
151
+ type: 'incremental' | 'snapshot'
152
+ }
153
+
154
+ type PhemexBookLevel = [number, number]
155
+
156
+ type PhemexBookMessage = {
157
+ book: {
158
+ asks: PhemexBookLevel[]
159
+ bids: PhemexBookLevel[]
160
+ }
161
+
162
+ symbol: string
163
+ timestamp: number
164
+ type: 'incremental' | 'snapshot'
165
+ }
166
+
167
+ type PhemexTicker = {
168
+ market24h: {
169
+ fundingRate: number
170
+ indexPrice: number
171
+ markPrice: number
172
+ openInterest: number
173
+ predFundingRate: number
174
+ symbol: string
175
+ close: number
176
+ }
177
+
178
+ timestamp: number
179
+ }
@@ -1,150 +1,150 @@
1
- import { BookChange, Trade } from '../types'
2
- import { Mapper } from './mapper'
3
-
4
- // https://docs.poloniex.com/#websocket-api
5
-
6
- export class PoloniexTradesMapper implements Mapper<'poloniex', Trade> {
7
- private readonly _channelIdToSymbolMap: Map<number, string> = new Map()
8
-
9
- canHandle(message: PoloniexPriceAggreatedMessage) {
10
- if (message.length < 3) {
11
- return false
12
- }
13
- // store mapping between channel id and symbols
14
- if (message[2][0][0] === 'i') {
15
- this._channelIdToSymbolMap.set(message[0], message[2][0][1].currencyPair)
16
- }
17
-
18
- return message[2].some((m) => m[0] === 't')
19
- }
20
-
21
- getFilters(symbols?: string[]) {
22
- return [
23
- {
24
- channel: 'price_aggregated_book',
25
- symbols
26
- } as const
27
- ]
28
- }
29
-
30
- *map(message: PoloniexPriceAggreatedMessage, localTimestamp: Date): IterableIterator<Trade> {
31
- const lastItem = message[message.length - 1]
32
- const symbol = typeof lastItem === 'string' ? lastItem : this._channelIdToSymbolMap.get(message[0])
33
-
34
- if (symbol === undefined) {
35
- return
36
- }
37
-
38
- for (const item of message[2]) {
39
- if (item[0] !== 't') {
40
- continue
41
- }
42
-
43
- const [_, id, side, price, size, timestamp] = item
44
-
45
- yield {
46
- type: 'trade',
47
- symbol,
48
- exchange: 'poloniex',
49
- id: String(id),
50
- price: Number(price),
51
- amount: Number(size),
52
- side: side === 1 ? 'buy' : 'sell',
53
- timestamp: new Date(timestamp * 1000),
54
- localTimestamp: localTimestamp
55
- }
56
- }
57
- }
58
- }
59
-
60
- const mapSnapshotLevels = (levels: { [key: string]: string }) => {
61
- return Object.keys(levels).map((key) => {
62
- return {
63
- price: Number(key),
64
- amount: Number(levels[key])
65
- }
66
- })
67
- }
68
-
69
- const mapBookLevel = (level: PoloniexBookUpdate) => {
70
- return {
71
- price: Number(level[2]),
72
- amount: Number(level[3])
73
- }
74
- }
75
-
76
- export class PoloniexBookChangeMapper implements Mapper<'poloniex', BookChange> {
77
- private readonly _channelIdToSymbolMap: Map<number, string> = new Map()
78
-
79
- canHandle(message: PoloniexPriceAggreatedMessage) {
80
- if (message.length < 3) {
81
- return false
82
- }
83
- // store mapping between channel id and symbols
84
- if (message[2][0][0] === 'i') {
85
- this._channelIdToSymbolMap.set(message[0], message[2][0][1].currencyPair)
86
- }
87
-
88
- return message[2].some((m) => m[0] === 'i' || m[0] === 'o')
89
- }
90
-
91
- getFilters(symbols?: string[]) {
92
- return [
93
- {
94
- channel: 'price_aggregated_book',
95
- symbols
96
- } as const
97
- ]
98
- }
99
-
100
- *map(message: PoloniexPriceAggreatedMessage, localTimestamp: Date): IterableIterator<BookChange> {
101
- const lastItem = message[message.length - 1]
102
- const symbol = typeof lastItem === 'string' ? lastItem : this._channelIdToSymbolMap.get(message[0])
103
-
104
- if (symbol === undefined) {
105
- return
106
- }
107
-
108
- let updates = []
109
-
110
- for (const item of message[2]) {
111
- if (item[0] === 'i') {
112
- const bookSnapshot: BookChange = {
113
- type: 'book_change',
114
- symbol,
115
- exchange: 'poloniex',
116
- isSnapshot: true,
117
- bids: mapSnapshotLevels(item[1].orderBook[1]),
118
- asks: mapSnapshotLevels(item[1].orderBook[0]),
119
- timestamp: localTimestamp,
120
- localTimestamp: localTimestamp
121
- }
122
-
123
- yield bookSnapshot
124
- } else if (item[0] === 'o') {
125
- updates.push(item)
126
- }
127
- }
128
-
129
- if (updates.length > 0) {
130
- const bookUpdate: BookChange = {
131
- type: 'book_change',
132
- symbol,
133
- exchange: 'poloniex',
134
- isSnapshot: false,
135
- bids: updates.filter((u) => u[1] == 1).map(mapBookLevel),
136
- asks: updates.filter((u) => u[1] == 0).map(mapBookLevel),
137
- timestamp: localTimestamp,
138
- localTimestamp: localTimestamp
139
- }
140
-
141
- yield bookUpdate
142
- }
143
- }
144
- }
145
-
146
- type PoloniexBookSnapshot = ['i', { currencyPair: string; orderBook: [{ [key: string]: string }, { [key: string]: string }] }]
147
- type PoloniexBookUpdate = ['o', 0 | 1, string, string]
148
- type PoloniexTrade = ['t', string, 1 | 0, string, string, number]
149
-
150
- type PoloniexPriceAggreatedMessage = [number, number, (PoloniexBookSnapshot | PoloniexBookUpdate | PoloniexTrade)[], string?]
1
+ import { BookChange, Trade } from '../types'
2
+ import { Mapper } from './mapper'
3
+
4
+ // https://docs.poloniex.com/#websocket-api
5
+
6
+ export class PoloniexTradesMapper implements Mapper<'poloniex', Trade> {
7
+ private readonly _channelIdToSymbolMap: Map<number, string> = new Map()
8
+
9
+ canHandle(message: PoloniexPriceAggreatedMessage) {
10
+ if (message.length < 3) {
11
+ return false
12
+ }
13
+ // store mapping between channel id and symbols
14
+ if (message[2][0][0] === 'i') {
15
+ this._channelIdToSymbolMap.set(message[0], message[2][0][1].currencyPair)
16
+ }
17
+
18
+ return message[2].some((m) => m[0] === 't')
19
+ }
20
+
21
+ getFilters(symbols?: string[]) {
22
+ return [
23
+ {
24
+ channel: 'price_aggregated_book',
25
+ symbols
26
+ } as const
27
+ ]
28
+ }
29
+
30
+ *map(message: PoloniexPriceAggreatedMessage, localTimestamp: Date): IterableIterator<Trade> {
31
+ const lastItem = message[message.length - 1]
32
+ const symbol = typeof lastItem === 'string' ? lastItem : this._channelIdToSymbolMap.get(message[0])
33
+
34
+ if (symbol === undefined) {
35
+ return
36
+ }
37
+
38
+ for (const item of message[2]) {
39
+ if (item[0] !== 't') {
40
+ continue
41
+ }
42
+
43
+ const [_, id, side, price, size, timestamp] = item
44
+
45
+ yield {
46
+ type: 'trade',
47
+ symbol,
48
+ exchange: 'poloniex',
49
+ id: String(id),
50
+ price: Number(price),
51
+ amount: Number(size),
52
+ side: side === 1 ? 'buy' : 'sell',
53
+ timestamp: new Date(timestamp * 1000),
54
+ localTimestamp: localTimestamp
55
+ }
56
+ }
57
+ }
58
+ }
59
+
60
+ const mapSnapshotLevels = (levels: { [key: string]: string }) => {
61
+ return Object.keys(levels).map((key) => {
62
+ return {
63
+ price: Number(key),
64
+ amount: Number(levels[key])
65
+ }
66
+ })
67
+ }
68
+
69
+ const mapBookLevel = (level: PoloniexBookUpdate) => {
70
+ return {
71
+ price: Number(level[2]),
72
+ amount: Number(level[3])
73
+ }
74
+ }
75
+
76
+ export class PoloniexBookChangeMapper implements Mapper<'poloniex', BookChange> {
77
+ private readonly _channelIdToSymbolMap: Map<number, string> = new Map()
78
+
79
+ canHandle(message: PoloniexPriceAggreatedMessage) {
80
+ if (message.length < 3) {
81
+ return false
82
+ }
83
+ // store mapping between channel id and symbols
84
+ if (message[2][0][0] === 'i') {
85
+ this._channelIdToSymbolMap.set(message[0], message[2][0][1].currencyPair)
86
+ }
87
+
88
+ return message[2].some((m) => m[0] === 'i' || m[0] === 'o')
89
+ }
90
+
91
+ getFilters(symbols?: string[]) {
92
+ return [
93
+ {
94
+ channel: 'price_aggregated_book',
95
+ symbols
96
+ } as const
97
+ ]
98
+ }
99
+
100
+ *map(message: PoloniexPriceAggreatedMessage, localTimestamp: Date): IterableIterator<BookChange> {
101
+ const lastItem = message[message.length - 1]
102
+ const symbol = typeof lastItem === 'string' ? lastItem : this._channelIdToSymbolMap.get(message[0])
103
+
104
+ if (symbol === undefined) {
105
+ return
106
+ }
107
+
108
+ let updates = []
109
+
110
+ for (const item of message[2]) {
111
+ if (item[0] === 'i') {
112
+ const bookSnapshot: BookChange = {
113
+ type: 'book_change',
114
+ symbol,
115
+ exchange: 'poloniex',
116
+ isSnapshot: true,
117
+ bids: mapSnapshotLevels(item[1].orderBook[1]),
118
+ asks: mapSnapshotLevels(item[1].orderBook[0]),
119
+ timestamp: localTimestamp,
120
+ localTimestamp: localTimestamp
121
+ }
122
+
123
+ yield bookSnapshot
124
+ } else if (item[0] === 'o') {
125
+ updates.push(item)
126
+ }
127
+ }
128
+
129
+ if (updates.length > 0) {
130
+ const bookUpdate: BookChange = {
131
+ type: 'book_change',
132
+ symbol,
133
+ exchange: 'poloniex',
134
+ isSnapshot: false,
135
+ bids: updates.filter((u) => u[1] == 1).map(mapBookLevel),
136
+ asks: updates.filter((u) => u[1] == 0).map(mapBookLevel),
137
+ timestamp: localTimestamp,
138
+ localTimestamp: localTimestamp
139
+ }
140
+
141
+ yield bookUpdate
142
+ }
143
+ }
144
+ }
145
+
146
+ type PoloniexBookSnapshot = ['i', { currencyPair: string; orderBook: [{ [key: string]: string }, { [key: string]: string }] }]
147
+ type PoloniexBookUpdate = ['o', 0 | 1, string, string]
148
+ type PoloniexTrade = ['t', string, 1 | 0, string, string, number]
149
+
150
+ type PoloniexPriceAggreatedMessage = [number, number, (PoloniexBookSnapshot | PoloniexBookUpdate | PoloniexTrade)[], string?]