tardis-dev 13.4.11 → 13.5.0
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/consts.d.ts +4 -1
- package/dist/consts.d.ts.map +1 -1
- package/dist/consts.js +11 -2
- package/dist/consts.js.map +1 -1
- package/dist/mappers/bybit.d.ts +1 -1
- package/dist/mappers/bybitspot.d.ts +96 -0
- package/dist/mappers/bybitspot.d.ts.map +1 -0
- package/dist/mappers/bybitspot.js +102 -0
- package/dist/mappers/bybitspot.js.map +1 -0
- package/dist/mappers/cryptocom.d.ts +257 -0
- package/dist/mappers/cryptocom.d.ts.map +1 -0
- package/dist/mappers/cryptocom.js +193 -0
- package/dist/mappers/cryptocom.js.map +1 -0
- package/dist/mappers/huobi.d.ts +3 -3
- package/dist/mappers/index.d.ts +4 -4
- package/dist/mappers/index.d.ts.map +1 -1
- package/dist/mappers/index.js +16 -4
- package/dist/mappers/index.js.map +1 -1
- package/dist/realtimefeeds/ascendex.d.ts +2 -0
- package/dist/realtimefeeds/ascendex.d.ts.map +1 -1
- package/dist/realtimefeeds/ascendex.js +6 -0
- package/dist/realtimefeeds/ascendex.js.map +1 -1
- package/dist/realtimefeeds/bybit.d.ts +2 -0
- package/dist/realtimefeeds/bybit.d.ts.map +1 -1
- package/dist/realtimefeeds/bybit.js +6 -0
- package/dist/realtimefeeds/bybit.js.map +1 -1
- package/dist/realtimefeeds/bybitspot.d.ts +10 -0
- package/dist/realtimefeeds/bybitspot.d.ts.map +1 -0
- package/dist/realtimefeeds/bybitspot.js +40 -0
- package/dist/realtimefeeds/bybitspot.js.map +1 -0
- package/dist/realtimefeeds/cryptocom.d.ts +10 -0
- package/dist/realtimefeeds/cryptocom.d.ts.map +1 -0
- package/dist/realtimefeeds/cryptocom.js +49 -0
- package/dist/realtimefeeds/cryptocom.js.map +1 -0
- package/dist/realtimefeeds/cryptocomderivatives.d.ts +10 -0
- package/dist/realtimefeeds/cryptocomderivatives.d.ts.map +1 -0
- package/dist/realtimefeeds/cryptocomderivatives.js +51 -0
- package/dist/realtimefeeds/cryptocomderivatives.js.map +1 -0
- package/dist/realtimefeeds/delta.d.ts +2 -0
- package/dist/realtimefeeds/delta.d.ts.map +1 -1
- package/dist/realtimefeeds/delta.js +6 -0
- package/dist/realtimefeeds/delta.js.map +1 -1
- package/dist/realtimefeeds/ftx.d.ts +2 -0
- package/dist/realtimefeeds/ftx.d.ts.map +1 -1
- package/dist/realtimefeeds/ftx.js +6 -0
- package/dist/realtimefeeds/ftx.js.map +1 -1
- package/dist/realtimefeeds/index.d.ts.map +1 -1
- package/dist/realtimefeeds/index.js +7 -1
- package/dist/realtimefeeds/index.js.map +1 -1
- package/dist/replay.d.ts.map +1 -1
- package/dist/replay.js +11 -0
- package/dist/replay.js.map +1 -1
- package/package.json +1 -1
- package/src/consts.ts +14 -2
- package/src/mappers/bybitspot.ts +129 -0
- package/src/mappers/cryptocom.ts +395 -0
- package/src/mappers/index.ts +16 -5
- package/src/realtimefeeds/ascendex.ts +8 -0
- package/src/realtimefeeds/bybit.ts +8 -0
- package/src/realtimefeeds/bybitspot.ts +39 -0
- package/src/realtimefeeds/cryptocom.ts +48 -0
- package/src/realtimefeeds/cryptocomderivatives.ts +50 -0
- package/src/realtimefeeds/delta.ts +8 -0
- package/src/realtimefeeds/ftx.ts +8 -0
- package/src/realtimefeeds/index.ts +7 -1
- package/src/replay.ts +13 -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
|
+
}
|
package/src/mappers/index.ts
CHANGED
|
@@ -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,
|
|
@@ -166,7 +168,10 @@ const tradesMappers = {
|
|
|
166
168
|
dydx: () => new DydxTradesMapper(),
|
|
167
169
|
serum: () => new SerumTradesMapper('serum'),
|
|
168
170
|
'star-atlas': () => new SerumTradesMapper('star-atlas'),
|
|
169
|
-
mango: () => new SerumTradesMapper('mango')
|
|
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')
|
|
170
175
|
}
|
|
171
176
|
|
|
172
177
|
const bookChangeMappers = {
|
|
@@ -216,7 +221,7 @@ const bookChangeMappers = {
|
|
|
216
221
|
'huobi-dm-swap': () => new HuobiBookChangeMapper('huobi-dm-swap'),
|
|
217
222
|
'huobi-dm-linear-swap': () => new HuobiBookChangeMapper('huobi-dm-linear-swap'),
|
|
218
223
|
'huobi-dm-options': () => new HuobiBookChangeMapper('huobi-dm-options'),
|
|
219
|
-
|
|
224
|
+
'bybit-spot': () => new BybitSpotBookChangeMapper('bybit-spot'),
|
|
220
225
|
bybit: () => new BybitBookChangeMapper('bybit', false),
|
|
221
226
|
okcoin: (localTimestamp: Date) =>
|
|
222
227
|
new OkexBookChangeMapper('okcoin', 'spot', localTimestamp.valueOf() >= new Date('2020-02-13').valueOf()),
|
|
@@ -234,7 +239,9 @@ const bookChangeMappers = {
|
|
|
234
239
|
dydx: () => new DydxBookChangeMapper(),
|
|
235
240
|
serum: () => new SerumBookChangeMapper('serum'),
|
|
236
241
|
'star-atlas': () => new SerumBookChangeMapper('star-atlas'),
|
|
237
|
-
mango: () => new SerumBookChangeMapper('mango')
|
|
242
|
+
mango: () => new SerumBookChangeMapper('mango'),
|
|
243
|
+
'crypto-com': () => new CryptoComBookChangeMapper('crypto-com'),
|
|
244
|
+
'crypto-com-derivatives': () => new CryptoComBookChangeMapper('crypto-com-derivatives')
|
|
238
245
|
}
|
|
239
246
|
|
|
240
247
|
const derivativeTickersMappers = {
|
|
@@ -262,7 +269,8 @@ const derivativeTickersMappers = {
|
|
|
262
269
|
'gate-io-futures': () => new GateIOFuturesDerivativeTickerMapper(),
|
|
263
270
|
coinflex: () => new CoinflexDerivativeTickerMapper(),
|
|
264
271
|
ascendex: () => new AscendexDerivativeTickerMapper(),
|
|
265
|
-
dydx: () => new DydxDerivativeTickerMapper()
|
|
272
|
+
dydx: () => new DydxDerivativeTickerMapper(),
|
|
273
|
+
'crypto-com-derivatives': () => new CryptoComDerivativeTickerMapper('crypto-com-derivatives')
|
|
266
274
|
}
|
|
267
275
|
|
|
268
276
|
const optionsSummaryMappers = {
|
|
@@ -338,7 +346,10 @@ const bookTickersMappers = {
|
|
|
338
346
|
serum: () => new SerumBookTickerMapper('serum'),
|
|
339
347
|
'star-atlas': () => new SerumBookTickerMapper('star-atlas'),
|
|
340
348
|
mango: () => new SerumBookTickerMapper('mango'),
|
|
341
|
-
'gate-io-futures': () => new GateIOFuturesBookTickerMapper('gate-io-futures')
|
|
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')
|
|
342
353
|
}
|
|
343
354
|
|
|
344
355
|
export const normalizeTrades = <T extends keyof typeof tradesMappers>(exchange: T, localTimestamp: Date): Mapper<T, Trade> => {
|
|
@@ -38,6 +38,14 @@ export class AscendexRealTimeFeed extends RealTimeFeedBase {
|
|
|
38
38
|
return message.m === 'error'
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
protected sendCustomPing = () => {
|
|
42
|
+
this.send({ op: 'ping' })
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
protected messageIsHeartbeat(msg: any) {
|
|
46
|
+
return msg.m === 'pong'
|
|
47
|
+
}
|
|
48
|
+
|
|
41
49
|
protected async provideManualSnapshots(filters: Filter<string>[], shouldCancel: () => boolean) {
|
|
42
50
|
const depthSnapshotChannel = filters.find((f) => f.channel === 'depth-snapshot-realtime')
|
|
43
51
|
if (!depthSnapshotChannel) {
|
|
@@ -90,4 +90,12 @@ class BybitSingleConnectionRealTimeDataFeed extends RealTimeFeedBase {
|
|
|
90
90
|
protected messageIsError(message: any): boolean {
|
|
91
91
|
return message.success === false
|
|
92
92
|
}
|
|
93
|
+
|
|
94
|
+
protected sendCustomPing = () => {
|
|
95
|
+
this.send({ op: 'ping' })
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
protected messageIsHeartbeat(msg: any) {
|
|
99
|
+
return msg.ret_msg === 'pong' || msg.op == 'pong'
|
|
100
|
+
}
|
|
93
101
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Filter } from '../types'
|
|
2
|
+
import { RealTimeFeedBase } from './realtimefeed'
|
|
3
|
+
|
|
4
|
+
export class BybitSpotRealTimeFeed extends RealTimeFeedBase {
|
|
5
|
+
protected wssURL = 'wss://stream.bybit.com/spot/quote/ws/v2'
|
|
6
|
+
|
|
7
|
+
protected mapToSubscribeMessages(filters: Filter<string>[]): any[] {
|
|
8
|
+
return filters
|
|
9
|
+
.map((filter) => {
|
|
10
|
+
if (!filter.symbols || filter.symbols.length === 0) {
|
|
11
|
+
throw new Error('BybitSpotRealTimeFeed requires explicitly specified symbols when subscribing to live feed')
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return filter.symbols.map((symbol) => {
|
|
15
|
+
return {
|
|
16
|
+
event: 'sub',
|
|
17
|
+
topic: filter.channel,
|
|
18
|
+
params: {
|
|
19
|
+
binary: false,
|
|
20
|
+
symbol: symbol
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
})
|
|
25
|
+
.flatMap((c) => c)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
protected messageIsError(message: any): boolean {
|
|
29
|
+
return message.code !== undefined && message.code !== '0'
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
protected sendCustomPing = () => {
|
|
33
|
+
this.send({ ping: new Date().valueOf() })
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
protected messageIsHeartbeat(msg: any) {
|
|
37
|
+
return msg.pong !== undefined
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Filter } from '../types'
|
|
2
|
+
import { RealTimeFeedBase } from './realtimefeed'
|
|
3
|
+
|
|
4
|
+
export class CryptoComRealTimeFeed extends RealTimeFeedBase {
|
|
5
|
+
protected wssURL = 'wss://stream.crypto.com/v2/market'
|
|
6
|
+
|
|
7
|
+
protected mapToSubscribeMessages(filters: Filter<string>[]): any[] {
|
|
8
|
+
const channels = filters
|
|
9
|
+
.map((filter) => {
|
|
10
|
+
if (!filter.symbols || filter.symbols.length === 0) {
|
|
11
|
+
throw new Error('CryptoComRealTimeFeed requires explicitly specified symbols when subscribing to live feed')
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return filter.symbols.map((symbol) => {
|
|
15
|
+
const suffix = filter.channel === 'book' ? '.150' : ''
|
|
16
|
+
return `${filter.channel}.${symbol}${suffix}`
|
|
17
|
+
})
|
|
18
|
+
})
|
|
19
|
+
.flatMap((s) => s)
|
|
20
|
+
|
|
21
|
+
return [
|
|
22
|
+
{
|
|
23
|
+
id: 1,
|
|
24
|
+
method: 'subscribe',
|
|
25
|
+
nonce: new Date().valueOf(),
|
|
26
|
+
params: {
|
|
27
|
+
channels: channels
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
protected messageIsError(message: any): boolean {
|
|
34
|
+
return message.code !== undefined && message.code !== 0
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
protected onMessage(msg: any) {
|
|
38
|
+
if (msg.method === 'public/heartbeat') {
|
|
39
|
+
this.send({
|
|
40
|
+
id: msg.id,
|
|
41
|
+
method: 'public/respond-heartbeat'
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
protected messageIsHeartbeat(msg: any) {
|
|
46
|
+
return msg.method === 'public/heartbeat'
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Filter } from '../types'
|
|
2
|
+
import { RealTimeFeedBase } from './realtimefeed'
|
|
3
|
+
|
|
4
|
+
export class CryptoComDerivativesRealTimeFeed extends RealTimeFeedBase {
|
|
5
|
+
protected wssURL = 'wss://deriv-stream.crypto.com/v1/market'
|
|
6
|
+
|
|
7
|
+
protected mapToSubscribeMessages(filters: Filter<string>[]): any[] {
|
|
8
|
+
const channels = filters
|
|
9
|
+
.map((filter) => {
|
|
10
|
+
if (!filter.symbols || filter.symbols.length === 0) {
|
|
11
|
+
throw new Error('CryptoComDerivativesRealTimeFeed requires explicitly specified symbols when subscribing to live feed')
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return filter.symbols.map((symbol) => {
|
|
15
|
+
const suffix = filter.channel === 'book' ? '.50' : ''
|
|
16
|
+
return `${filter.channel}.${symbol}${suffix}`
|
|
17
|
+
})
|
|
18
|
+
})
|
|
19
|
+
.flatMap((s) => s)
|
|
20
|
+
|
|
21
|
+
return [
|
|
22
|
+
{
|
|
23
|
+
id: 1,
|
|
24
|
+
method: 'subscribe',
|
|
25
|
+
nonce: new Date().valueOf(),
|
|
26
|
+
params: {
|
|
27
|
+
channels: channels,
|
|
28
|
+
book_subscription_type: 'SNAPSHOT_AND_UPDATE',
|
|
29
|
+
book_update_frequency: 5
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
protected messageIsError(message: any): boolean {
|
|
36
|
+
return message.code !== undefined && message.code !== 0 && message.code !== 40003
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
protected onMessage(msg: any) {
|
|
40
|
+
if (msg.method === 'public/heartbeat') {
|
|
41
|
+
this.send({
|
|
42
|
+
id: msg.id,
|
|
43
|
+
method: 'public/respond-heartbeat'
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
protected messageIsHeartbeat(msg: any) {
|
|
48
|
+
return msg.method === 'public/heartbeat'
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -24,4 +24,12 @@ export class DeltaRealTimeFeed extends RealTimeFeedBase {
|
|
|
24
24
|
protected messageIsError(message: any): boolean {
|
|
25
25
|
return message.error !== undefined && message.error !== null
|
|
26
26
|
}
|
|
27
|
+
|
|
28
|
+
protected sendCustomPing = () => {
|
|
29
|
+
this.send({ type: 'ping' })
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
protected messageIsHeartbeat(msg: any) {
|
|
33
|
+
return msg.type === 'pong'
|
|
34
|
+
}
|
|
27
35
|
}
|
package/src/realtimefeeds/ftx.ts
CHANGED
|
@@ -63,6 +63,14 @@ class FtxSingleConnectionRealTimeFeed extends RealTimeFeedBase {
|
|
|
63
63
|
// ignore market not found errors
|
|
64
64
|
return message.code == 404
|
|
65
65
|
}
|
|
66
|
+
|
|
67
|
+
protected sendCustomPing = () => {
|
|
68
|
+
this.send({ op: 'ping' })
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
protected messageIsHeartbeat(msg: any) {
|
|
72
|
+
return msg.type === 'pong'
|
|
73
|
+
}
|
|
66
74
|
}
|
|
67
75
|
|
|
68
76
|
class FTXInstrumentInfoClient extends PoolingClientBase {
|
|
@@ -41,6 +41,9 @@ import { DydxRealTimeFeed } from './dydx'
|
|
|
41
41
|
import { SerumRealTimeFeed } from './serum'
|
|
42
42
|
import { StarAtlasRealTimeFeed } from './staratlas'
|
|
43
43
|
import { MangoRealTimeFeed } from './mango'
|
|
44
|
+
import { BybitSpotRealTimeFeed } from './bybitspot'
|
|
45
|
+
import { CryptoComRealTimeFeed } from './cryptocom'
|
|
46
|
+
import { CryptoComDerivativesRealTimeFeed } from './cryptocomderivatives'
|
|
44
47
|
|
|
45
48
|
export * from './realtimefeed'
|
|
46
49
|
|
|
@@ -89,7 +92,10 @@ const realTimeFeedsMap: {
|
|
|
89
92
|
serum: SerumRealTimeFeed,
|
|
90
93
|
'star-atlas': StarAtlasRealTimeFeed,
|
|
91
94
|
'huobi-dm-options': HuobiDMOptionsRealTimeFeed,
|
|
92
|
-
mango: MangoRealTimeFeed
|
|
95
|
+
mango: MangoRealTimeFeed,
|
|
96
|
+
'bybit-spot': BybitSpotRealTimeFeed,
|
|
97
|
+
'crypto-com': CryptoComRealTimeFeed,
|
|
98
|
+
'crypto-com-derivatives': CryptoComDerivativesRealTimeFeed
|
|
93
99
|
}
|
|
94
100
|
|
|
95
101
|
export function getRealTimeFeedFactory(exchange: Exchange): RealTimeFeed {
|