tardis-dev 12.5.22 → 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.
- package/dist/apikeyaccessinfo.js +1 -1
- package/dist/apikeyaccessinfo.js.map +1 -1
- package/dist/clearcache.js +12 -12
- package/dist/clearcache.js.map +1 -1
- package/dist/combine.js +1 -1
- package/dist/combine.js.map +1 -1
- package/dist/computable/booksnapshot.d.ts.map +1 -1
- package/dist/computable/booksnapshot.js +1 -1
- package/dist/computable/booksnapshot.js.map +1 -1
- package/dist/computable/tradebar.d.ts.map +1 -1
- package/dist/computable/tradebar.js.map +1 -1
- package/dist/debug.js +1 -1
- package/dist/debug.js.map +1 -1
- package/dist/downloaddatasets.js +13 -13
- package/dist/downloaddatasets.js.map +1 -1
- package/dist/exchangedetails.js +1 -1
- package/dist/exchangedetails.js.map +1 -1
- package/dist/filter.js.map +1 -1
- package/dist/handy.js +10 -10
- 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 +2 -2
- package/dist/mappers/binance.js.map +1 -1
- package/dist/mappers/binanceoptions.js +10 -10
- package/dist/mappers/binanceoptions.js.map +1 -1
- package/dist/mappers/bitflyer.js +1 -1
- package/dist/mappers/bitflyer.js.map +1 -1
- package/dist/mappers/bybit.d.ts +12 -1
- package/dist/mappers/bybit.d.ts.map +1 -1
- package/dist/mappers/bybit.js +21 -3
- package/dist/mappers/bybit.js.map +1 -1
- package/dist/mappers/coinbase.js +2 -2
- package/dist/mappers/coinbase.js.map +1 -1
- package/dist/mappers/dydx.d.ts +6 -14
- package/dist/mappers/dydx.d.ts.map +1 -1
- package/dist/mappers/dydx.js +1 -1
- package/dist/mappers/dydx.js.map +1 -1
- package/dist/mappers/ftx.js +2 -2
- package/dist/mappers/ftx.js.map +1 -1
- package/dist/mappers/huobi.d.ts.map +1 -1
- package/dist/mappers/huobi.js +11 -11
- package/dist/mappers/huobi.js.map +1 -1
- package/dist/mappers/okex.js +14 -14
- package/dist/mappers/okex.js.map +1 -1
- package/dist/mappers/phemex.d.ts.map +1 -1
- package/dist/mappers/phemex.js.map +1 -1
- package/dist/realtimefeeds/ascendex.js +2 -2
- package/dist/realtimefeeds/ascendex.js.map +1 -1
- package/dist/realtimefeeds/binance.js +1 -1
- package/dist/realtimefeeds/binance.js.map +1 -1
- package/dist/realtimefeeds/bitmex.js +1 -1
- package/dist/realtimefeeds/bitmex.js.map +1 -1
- package/dist/realtimefeeds/ftx.js +1 -1
- package/dist/realtimefeeds/ftx.js.map +1 -1
- package/dist/realtimefeeds/huobi.js +7 -7
- package/dist/realtimefeeds/huobi.js.map +1 -1
- package/dist/realtimefeeds/okex.js +1 -1
- package/dist/realtimefeeds/okex.js.map +1 -1
- package/dist/realtimefeeds/realtimefeed.js +9 -9
- package/dist/realtimefeeds/realtimefeed.js.map +1 -1
- package/dist/replay.d.ts.map +1 -1
- package/dist/replay.js +75 -40
- package/dist/replay.js.map +1 -1
- package/dist/stream.js +4 -4
- package/dist/stream.js.map +1 -1
- package/dist/worker.js +12 -12
- package/dist/worker.js.map +1 -1
- package/package.json +19 -18
- package/src/computable/booksnapshot.ts +4 -2
- package/src/computable/tradebar.ts +4 -1
- package/src/downloaddatasets.ts +188 -188
- package/src/filter.ts +69 -69
- package/src/handy.ts +2 -2
- package/src/instrumentinfo.ts +1 -1
- package/src/mappers/ascendex.ts +156 -156
- package/src/mappers/binance.ts +6 -3
- package/src/mappers/bybit.ts +28 -4
- package/src/mappers/coinflex.ts +159 -159
- package/src/mappers/delta.ts +175 -175
- package/src/mappers/dydx.ts +303 -306
- package/src/mappers/gateio.ts +117 -117
- package/src/mappers/gateiofutures.ts +185 -185
- package/src/mappers/huobi.ts +4 -2
- package/src/mappers/phemex.ts +179 -177
- package/src/mappers/poloniex.ts +150 -150
- package/src/mappers/serum.ts +103 -103
- package/src/mappers/upbit.ts +104 -104
- package/src/realtimefeeds/ascendex.ts +65 -65
- package/src/realtimefeeds/coinflex.ts +29 -29
- package/src/realtimefeeds/delta.ts +27 -27
- package/src/realtimefeeds/dydx.ts +40 -40
- package/src/realtimefeeds/gateio.ts +41 -41
- package/src/realtimefeeds/gateiofutures.ts +90 -90
- package/src/realtimefeeds/poloniex.ts +28 -28
- package/src/realtimefeeds/realtimefeed.ts +2 -2
- package/src/realtimefeeds/upbit.ts +35 -35
- package/src/replay.ts +61 -18
- package/src/stream.ts +1 -1
package/src/mappers/phemex.ts
CHANGED
|
@@ -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 =
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
pendingTickerInfo.
|
|
133
|
-
|
|
134
|
-
pendingTickerInfo.
|
|
135
|
-
pendingTickerInfo.
|
|
136
|
-
pendingTickerInfo.
|
|
137
|
-
pendingTickerInfo.
|
|
138
|
-
pendingTickerInfo.
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
type
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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
|
+
}
|
package/src/mappers/poloniex.ts
CHANGED
|
@@ -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?]
|