tardis-dev 16.5.1 → 16.6.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 +3 -1
- package/dist/consts.d.ts.map +1 -1
- package/dist/consts.js +21 -1
- package/dist/consts.js.map +1 -1
- package/dist/handy.d.ts.map +1 -1
- package/dist/handy.js +6 -3
- package/dist/handy.js.map +1 -1
- package/dist/mappers/ascendex.d.ts +6 -99
- package/dist/mappers/ascendex.d.ts.map +1 -1
- package/dist/mappers/ascendex.js +13 -4
- package/dist/mappers/ascendex.js.map +1 -1
- package/dist/mappers/binance.d.ts +27 -154
- package/dist/mappers/binance.d.ts.map +1 -1
- package/dist/mappers/binance.js +49 -15
- package/dist/mappers/binance.js.map +1 -1
- package/dist/mappers/binancedex.d.ts +7 -4
- package/dist/mappers/binancedex.d.ts.map +1 -1
- package/dist/mappers/binancedex.js +11 -3
- package/dist/mappers/binancedex.js.map +1 -1
- package/dist/mappers/binanceeuropeanoptions.d.ts +6 -216
- package/dist/mappers/binanceeuropeanoptions.d.ts.map +1 -1
- package/dist/mappers/binanceeuropeanoptions.js +26 -7
- package/dist/mappers/binanceeuropeanoptions.js.map +1 -1
- package/dist/mappers/bitfinex.d.ts +15 -100
- package/dist/mappers/bitfinex.d.ts.map +1 -1
- package/dist/mappers/bitfinex.js +20 -5
- package/dist/mappers/bitfinex.js.map +1 -1
- package/dist/mappers/bitflyer.d.ts +5 -41
- package/dist/mappers/bitflyer.d.ts.map +1 -1
- package/dist/mappers/bitflyer.js +11 -3
- package/dist/mappers/bitflyer.js.map +1 -1
- package/dist/mappers/bitget.d.ts +12 -269
- package/dist/mappers/bitget.d.ts.map +1 -1
- package/dist/mappers/bitget.js +46 -9
- package/dist/mappers/bitget.js.map +1 -1
- package/dist/mappers/bitmex.d.ts +8 -56
- package/dist/mappers/bitmex.d.ts.map +1 -1
- package/dist/mappers/bitmex.js +15 -5
- package/dist/mappers/bitmex.js.map +1 -1
- package/dist/mappers/bitnomial.d.ts +4 -44
- package/dist/mappers/bitnomial.d.ts.map +1 -1
- package/dist/mappers/bitnomial.js +9 -2
- package/dist/mappers/bitnomial.js.map +1 -1
- package/dist/mappers/bitstamp.d.ts +4 -44
- package/dist/mappers/bitstamp.d.ts.map +1 -1
- package/dist/mappers/bitstamp.js +9 -2
- package/dist/mappers/bitstamp.js.map +1 -1
- package/dist/mappers/blockchaincom.d.ts +4 -63
- package/dist/mappers/blockchaincom.d.ts.map +1 -1
- package/dist/mappers/blockchaincom.js +9 -2
- package/dist/mappers/blockchaincom.js.map +1 -1
- package/dist/mappers/bullish.d.ts +8 -158
- package/dist/mappers/bullish.d.ts.map +1 -1
- package/dist/mappers/bullish.js +15 -5
- package/dist/mappers/bullish.js.map +1 -1
- package/dist/mappers/bybit.d.ts +61 -407
- package/dist/mappers/bybit.d.ts.map +1 -1
- package/dist/mappers/bybit.js +60 -15
- package/dist/mappers/bybit.js.map +1 -1
- package/dist/mappers/bybitspot.d.ts +1 -1
- package/dist/mappers/coinbase.d.ts +6 -39
- package/dist/mappers/coinbase.d.ts.map +1 -1
- package/dist/mappers/coinbase.js +11 -3
- package/dist/mappers/coinbase.js.map +1 -1
- package/dist/mappers/coinbaseinternational.d.ts +7 -78
- package/dist/mappers/coinbaseinternational.d.ts.map +1 -1
- package/dist/mappers/coinbaseinternational.js +13 -4
- package/dist/mappers/coinbaseinternational.js.map +1 -1
- package/dist/mappers/coinflex.d.ts +6 -24
- package/dist/mappers/coinflex.d.ts.map +1 -1
- package/dist/mappers/coinflex.js +11 -3
- package/dist/mappers/coinflex.js.map +1 -1
- package/dist/mappers/cryptocom.d.ts +22 -328
- package/dist/mappers/cryptocom.d.ts.map +1 -1
- package/dist/mappers/cryptocom.js +13 -4
- package/dist/mappers/cryptocom.js.map +1 -1
- package/dist/mappers/cryptofacilities.d.ts +8 -96
- package/dist/mappers/cryptofacilities.d.ts.map +1 -1
- package/dist/mappers/cryptofacilities.js +24 -7
- package/dist/mappers/cryptofacilities.js.map +1 -1
- package/dist/mappers/delta.d.ts +7 -114
- package/dist/mappers/delta.d.ts.map +1 -1
- package/dist/mappers/delta.js +30 -10
- package/dist/mappers/delta.js.map +1 -1
- package/dist/mappers/deribit.d.ts +8 -66
- package/dist/mappers/deribit.d.ts.map +1 -1
- package/dist/mappers/deribit.js +17 -6
- package/dist/mappers/deribit.js.map +1 -1
- package/dist/mappers/dydx.d.ts +5 -146
- package/dist/mappers/dydx.d.ts.map +1 -1
- package/dist/mappers/dydx.js +11 -3
- package/dist/mappers/dydx.js.map +1 -1
- package/dist/mappers/dydxv4.d.ts +6 -173
- package/dist/mappers/dydxv4.d.ts.map +1 -1
- package/dist/mappers/dydxv4.js +13 -4
- package/dist/mappers/dydxv4.js.map +1 -1
- package/dist/mappers/ftx.d.ts +12 -107
- package/dist/mappers/ftx.d.ts.map +1 -1
- package/dist/mappers/ftx.js +21 -6
- package/dist/mappers/ftx.js.map +1 -1
- package/dist/mappers/gateio.d.ts +6 -191
- package/dist/mappers/gateio.d.ts.map +1 -1
- package/dist/mappers/gateio.js +28 -8
- package/dist/mappers/gateio.js.map +1 -1
- package/dist/mappers/gateiofutures.d.ts +7 -122
- package/dist/mappers/gateiofutures.d.ts.map +1 -1
- package/dist/mappers/gateiofutures.js +13 -4
- package/dist/mappers/gateiofutures.js.map +1 -1
- package/dist/mappers/gemini.d.ts +6 -3
- package/dist/mappers/gemini.d.ts.map +1 -1
- package/dist/mappers/gemini.js +9 -2
- package/dist/mappers/gemini.js.map +1 -1
- package/dist/mappers/hitbtc.d.ts +6 -3
- package/dist/mappers/hitbtc.d.ts.map +1 -1
- package/dist/mappers/hitbtc.js +9 -2
- package/dist/mappers/hitbtc.js.map +1 -1
- package/dist/mappers/huobi.d.ts +118 -289
- package/dist/mappers/huobi.d.ts.map +1 -1
- package/dist/mappers/huobi.js +45 -7
- package/dist/mappers/huobi.js.map +1 -1
- package/dist/mappers/hyperliquid.d.ts +6 -86
- package/dist/mappers/hyperliquid.d.ts.map +1 -1
- package/dist/mappers/hyperliquid.js +13 -4
- package/dist/mappers/hyperliquid.js.map +1 -1
- package/dist/mappers/index.d.ts +784 -272
- package/dist/mappers/index.d.ts.map +1 -1
- package/dist/mappers/index.js +64 -432
- package/dist/mappers/index.js.map +1 -1
- package/dist/mappers/kraken.d.ts +7 -4
- package/dist/mappers/kraken.d.ts.map +1 -1
- package/dist/mappers/kraken.js +11 -3
- package/dist/mappers/kraken.js.map +1 -1
- package/dist/mappers/kucoin.d.ts +6 -122
- package/dist/mappers/kucoin.d.ts.map +1 -1
- package/dist/mappers/kucoin.js +13 -5
- package/dist/mappers/kucoin.js.map +1 -1
- package/dist/mappers/kucoinfutures.d.ts +6 -207
- package/dist/mappers/kucoinfutures.d.ts.map +1 -1
- package/dist/mappers/kucoinfutures.js +15 -6
- package/dist/mappers/kucoinfutures.js.map +1 -1
- package/dist/mappers/lighter.d.ts +8 -156
- package/dist/mappers/lighter.d.ts.map +1 -1
- package/dist/mappers/lighter.js +15 -5
- package/dist/mappers/lighter.js.map +1 -1
- package/dist/mappers/mapper.d.ts +3 -1
- package/dist/mappers/mapper.d.ts.map +1 -1
- package/dist/mappers/mapper.js.map +1 -1
- package/dist/mappers/mexc.d.ts +122 -0
- package/dist/mappers/mexc.d.ts.map +1 -0
- package/dist/mappers/mexc.js +205 -0
- package/dist/mappers/mexc.js.map +1 -0
- package/dist/mappers/mexcfutures.d.ts +137 -0
- package/dist/mappers/mexcfutures.d.ts.map +1 -0
- package/dist/mappers/mexcfutures.js +225 -0
- package/dist/mappers/mexcfutures.js.map +1 -0
- package/dist/mappers/okex.d.ts +36 -473
- package/dist/mappers/okex.d.ts.map +1 -1
- package/dist/mappers/okex.js +143 -37
- package/dist/mappers/okex.js.map +1 -1
- package/dist/mappers/phemex.d.ts +5 -82
- package/dist/mappers/phemex.d.ts.map +1 -1
- package/dist/mappers/phemex.js +22 -4
- package/dist/mappers/phemex.js.map +1 -1
- package/dist/mappers/poloniex.d.ts +5 -90
- package/dist/mappers/poloniex.d.ts.map +1 -1
- package/dist/mappers/poloniex.js +18 -4
- package/dist/mappers/poloniex.js.map +1 -1
- package/dist/mappers/polymarket.d.ts +7 -31
- package/dist/mappers/polymarket.d.ts.map +1 -1
- package/dist/mappers/polymarket.js +11 -3
- package/dist/mappers/polymarket.js.map +1 -1
- package/dist/mappers/registry.d.ts +41 -0
- package/dist/mappers/registry.d.ts.map +1 -0
- package/dist/mappers/registry.js +111 -0
- package/dist/mappers/registry.js.map +1 -0
- package/dist/mappers/serum.d.ts +16 -89
- package/dist/mappers/serum.d.ts.map +1 -1
- package/dist/mappers/serum.js +21 -3
- package/dist/mappers/serum.js.map +1 -1
- package/dist/mappers/upbit.d.ts +5 -47
- package/dist/mappers/upbit.d.ts.map +1 -1
- package/dist/mappers/upbit.js +9 -2
- package/dist/mappers/upbit.js.map +1 -1
- package/dist/mappers/woox.d.ts +6 -107
- package/dist/mappers/woox.d.ts.map +1 -1
- package/dist/mappers/woox.js +13 -4
- package/dist/mappers/woox.js.map +1 -1
- package/dist/okexsymbols.d.ts +3 -0
- package/dist/okexsymbols.d.ts.map +1 -0
- package/dist/okexsymbols.js +10 -0
- package/dist/okexsymbols.js.map +1 -0
- package/dist/realtimefeeds/hyperliquid.d.ts.map +1 -1
- package/dist/realtimefeeds/hyperliquid.js +3 -1
- package/dist/realtimefeeds/hyperliquid.js.map +1 -1
- package/dist/realtimefeeds/index.d.ts.map +1 -1
- package/dist/realtimefeeds/index.js +4 -0
- package/dist/realtimefeeds/index.js.map +1 -1
- package/dist/realtimefeeds/mexc.d.ts +35 -0
- package/dist/realtimefeeds/mexc.d.ts.map +1 -0
- package/dist/realtimefeeds/mexc.js +261 -0
- package/dist/realtimefeeds/mexc.js.map +1 -0
- package/dist/realtimefeeds/mexcfutures.d.ts +25 -0
- package/dist/realtimefeeds/mexcfutures.d.ts.map +1 -0
- package/dist/realtimefeeds/mexcfutures.js +203 -0
- package/dist/realtimefeeds/mexcfutures.js.map +1 -0
- package/dist/realtimefeeds/okex.d.ts +1 -0
- package/dist/realtimefeeds/okex.d.ts.map +1 -1
- package/dist/realtimefeeds/okex.js +7 -5
- package/dist/realtimefeeds/okex.js.map +1 -1
- package/dist/realtimefeeds/realtimefeed.d.ts +1 -0
- package/dist/realtimefeeds/realtimefeed.d.ts.map +1 -1
- package/dist/realtimefeeds/realtimefeed.js +4 -1
- package/dist/realtimefeeds/realtimefeed.js.map +1 -1
- package/dist/replay.d.ts.map +1 -1
- package/dist/replay.js +62 -13
- package/dist/replay.js.map +1 -1
- package/example.js +133 -31
- package/package.json +2 -1
- package/src/consts.ts +22 -1
- package/src/handy.ts +6 -3
- package/src/mappers/ascendex.ts +14 -4
- package/src/mappers/binance.ts +61 -21
- package/src/mappers/binancedex.ts +12 -3
- package/src/mappers/binanceeuropeanoptions.ts +28 -7
- package/src/mappers/bitfinex.ts +21 -5
- package/src/mappers/bitflyer.ts +12 -3
- package/src/mappers/bitget.ts +48 -9
- package/src/mappers/bitmex.ts +16 -5
- package/src/mappers/bitnomial.ts +10 -2
- package/src/mappers/bitstamp.ts +10 -2
- package/src/mappers/blockchaincom.ts +10 -2
- package/src/mappers/bullish.ts +16 -5
- package/src/mappers/bybit.ts +70 -15
- package/src/mappers/coinbase.ts +12 -3
- package/src/mappers/coinbaseinternational.ts +14 -4
- package/src/mappers/coinflex.ts +12 -3
- package/src/mappers/cryptocom.ts +14 -4
- package/src/mappers/cryptofacilities.ts +30 -6
- package/src/mappers/delta.ts +41 -7
- package/src/mappers/deribit.ts +18 -6
- package/src/mappers/dydx.ts +12 -3
- package/src/mappers/dydxv4.ts +14 -4
- package/src/mappers/ftx.ts +22 -6
- package/src/mappers/gateio.ts +34 -8
- package/src/mappers/gateiofutures.ts +14 -4
- package/src/mappers/gemini.ts +10 -2
- package/src/mappers/hitbtc.ts +10 -2
- package/src/mappers/huobi.ts +47 -10
- package/src/mappers/hyperliquid.ts +14 -4
- package/src/mappers/index.ts +133 -679
- package/src/mappers/kraken.ts +12 -3
- package/src/mappers/kucoin.ts +19 -5
- package/src/mappers/kucoinfutures.ts +20 -5
- package/src/mappers/lighter.ts +16 -5
- package/src/mappers/mapper.ts +3 -1
- package/src/mappers/mexc.ts +324 -0
- package/src/mappers/mexcfutures.ts +352 -0
- package/src/mappers/okex.ts +178 -37
- package/src/mappers/phemex.ts +25 -4
- package/src/mappers/poloniex.ts +20 -4
- package/src/mappers/polymarket.ts +12 -3
- package/src/mappers/registry.ts +203 -0
- package/src/mappers/serum.ts +22 -3
- package/src/mappers/upbit.ts +10 -2
- package/src/mappers/woox.ts +14 -4
- package/src/okexsymbols.ts +10 -0
- package/src/realtimefeeds/hyperliquid.ts +4 -1
- package/src/realtimefeeds/index.ts +4 -0
- package/src/realtimefeeds/mexc.ts +327 -0
- package/src/realtimefeeds/mexcfutures.ts +269 -0
- package/src/realtimefeeds/okex.ts +7 -5
- package/src/realtimefeeds/realtimefeed.ts +5 -1
- package/src/replay.ts +73 -15
package/src/mappers/kraken.ts
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import { asNonZeroNumberOrUndefined, upperCaseSymbols } from '../handy.ts'
|
|
2
2
|
import { BookChange, BookTicker, Trade } from '../types.ts'
|
|
3
3
|
import { Mapper } from './mapper.ts'
|
|
4
|
+
import { exchangeMappers } from './registry.ts'
|
|
4
5
|
|
|
5
6
|
// https://www.kraken.com/features/websocket-api
|
|
6
7
|
|
|
7
|
-
export const
|
|
8
|
+
export const krakenMappers = exchangeMappers({
|
|
9
|
+
kraken: {
|
|
10
|
+
trades: () => krakenTradesMapper,
|
|
11
|
+
bookChanges: () => krakenBookChangeMapper,
|
|
12
|
+
bookTickers: () => krakenBookTickerMapper
|
|
13
|
+
}
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
const krakenTradesMapper: Mapper<'kraken', Trade> = {
|
|
8
17
|
canHandle(message: KrakenTrades) {
|
|
9
18
|
if (!Array.isArray(message)) {
|
|
10
19
|
return false
|
|
@@ -64,7 +73,7 @@ const getLatestTimestamp = (bids: KrakenBookLevel[], asks: KrakenBookLevel[]): D
|
|
|
64
73
|
return timestamp
|
|
65
74
|
}
|
|
66
75
|
|
|
67
|
-
|
|
76
|
+
const krakenBookChangeMapper: Mapper<'kraken', BookChange> = {
|
|
68
77
|
canHandle(message: KrakenBookSnapshot | KrakenBookUpdate) {
|
|
69
78
|
if (!Array.isArray(message)) {
|
|
70
79
|
return false
|
|
@@ -122,7 +131,7 @@ export const krakenBookChangeMapper: Mapper<'kraken', BookChange> = {
|
|
|
122
131
|
}
|
|
123
132
|
}
|
|
124
133
|
|
|
125
|
-
|
|
134
|
+
const krakenBookTickerMapper: Mapper<'kraken', BookTicker> = {
|
|
126
135
|
canHandle(message: KrakenSpread) {
|
|
127
136
|
if (!Array.isArray(message)) {
|
|
128
137
|
return false
|
package/src/mappers/kucoin.ts
CHANGED
|
@@ -2,8 +2,18 @@ import { debug } from '../debug.ts'
|
|
|
2
2
|
import { CircularBuffer, upperCaseSymbols } from '../handy.ts'
|
|
3
3
|
import { BookChange, Exchange, BookTicker, Trade, BookPriceLevel } from '../types.ts'
|
|
4
4
|
import { Mapper } from './mapper.ts'
|
|
5
|
+
import { exchangeMappers, isRealTime } from './registry.ts'
|
|
6
|
+
|
|
7
|
+
export const kucoinMappers = exchangeMappers({
|
|
8
|
+
kucoin: {
|
|
9
|
+
trades: () => new KucoinTradesMapper('kucoin'),
|
|
10
|
+
bookChanges: (localTimestamp) =>
|
|
11
|
+
new KucoinBookChangeMapper('kucoin', { ignoreBookSnapshotOverlapError: isRealTime(localTimestamp) === false }),
|
|
12
|
+
bookTickers: () => new KucoinBookTickerMapper('kucoin')
|
|
13
|
+
}
|
|
14
|
+
})
|
|
5
15
|
|
|
6
|
-
|
|
16
|
+
class KucoinTradesMapper implements Mapper<'kucoin', Trade> {
|
|
7
17
|
constructor(private readonly _exchange: Exchange) {}
|
|
8
18
|
canHandle(message: KucoinTradeMessage) {
|
|
9
19
|
return message.type === 'message' && message.topic.startsWith('/market/match')
|
|
@@ -41,15 +51,19 @@ export class KucoinTradesMapper implements Mapper<'kucoin', Trade> {
|
|
|
41
51
|
}
|
|
42
52
|
}
|
|
43
53
|
|
|
44
|
-
|
|
54
|
+
class KucoinBookChangeMapper implements Mapper<'kucoin', BookChange> {
|
|
45
55
|
protected readonly symbolToDepthInfoMapping: {
|
|
46
56
|
[key: string]: LocalDepthInfo
|
|
47
57
|
} = {}
|
|
48
58
|
|
|
49
59
|
constructor(
|
|
50
60
|
protected readonly _exchange: Exchange,
|
|
51
|
-
|
|
52
|
-
) {
|
|
61
|
+
{ ignoreBookSnapshotOverlapError }: { ignoreBookSnapshotOverlapError: boolean }
|
|
62
|
+
) {
|
|
63
|
+
this.ignoreBookSnapshotOverlapError = ignoreBookSnapshotOverlapError
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private readonly ignoreBookSnapshotOverlapError: boolean
|
|
53
67
|
|
|
54
68
|
canHandle(message: KucoinLevel2SnapshotMessage | KucoinLevel2UpdateMessage) {
|
|
55
69
|
return message.type === 'message' && message.topic.startsWith('/market/level2')
|
|
@@ -221,7 +235,7 @@ export class KucoinBookChangeMapper implements Mapper<'kucoin', BookChange> {
|
|
|
221
235
|
}
|
|
222
236
|
}
|
|
223
237
|
|
|
224
|
-
|
|
238
|
+
class KucoinBookTickerMapper implements Mapper<'kucoin', BookTicker> {
|
|
225
239
|
constructor(protected readonly _exchange: Exchange) {}
|
|
226
240
|
|
|
227
241
|
canHandle(message: KucoinTickerMessage) {
|
|
@@ -2,8 +2,19 @@ import { debug } from '../debug.ts'
|
|
|
2
2
|
import { asNonZeroNumberOrUndefined, CircularBuffer, upperCaseSymbols } from '../handy.ts'
|
|
3
3
|
import { BookChange, BookTicker, DerivativeTicker, Trade } from '../types.ts'
|
|
4
4
|
import { Mapper, PendingTickerInfoHelper } from './mapper.ts'
|
|
5
|
+
import { exchangeMappers, isRealTime } from './registry.ts'
|
|
6
|
+
|
|
7
|
+
export const kucoinFuturesMappers = exchangeMappers({
|
|
8
|
+
'kucoin-futures': {
|
|
9
|
+
trades: () => new KucoinFuturesTradesMapper(),
|
|
10
|
+
bookChanges: (localTimestamp) =>
|
|
11
|
+
new KucoinFuturesBookChangeMapper({ ignoreBookSnapshotOverlapError: isRealTime(localTimestamp) === false }),
|
|
12
|
+
derivativeTickers: () => new KucoinFuturesDerivativeTickerMapper(),
|
|
13
|
+
bookTickers: () => new KucoinFuturesBookTickerMapper()
|
|
14
|
+
}
|
|
15
|
+
})
|
|
5
16
|
|
|
6
|
-
|
|
17
|
+
class KucoinFuturesTradesMapper implements Mapper<'kucoin-futures', Trade> {
|
|
7
18
|
canHandle(message: KucoinFuturesTradeMessage) {
|
|
8
19
|
return message.type === 'message' && message.topic.startsWith('/contractMarket/execution')
|
|
9
20
|
}
|
|
@@ -38,12 +49,16 @@ export class KucoinFuturesTradesMapper implements Mapper<'kucoin-futures', Trade
|
|
|
38
49
|
}
|
|
39
50
|
}
|
|
40
51
|
|
|
41
|
-
|
|
52
|
+
class KucoinFuturesBookChangeMapper implements Mapper<'kucoin-futures', BookChange> {
|
|
42
53
|
protected readonly symbolToDepthInfoMapping: {
|
|
43
54
|
[key: string]: LocalDepthInfo
|
|
44
55
|
} = {}
|
|
45
56
|
|
|
46
|
-
|
|
57
|
+
private readonly ignoreBookSnapshotOverlapError: boolean
|
|
58
|
+
|
|
59
|
+
constructor({ ignoreBookSnapshotOverlapError }: { ignoreBookSnapshotOverlapError: boolean }) {
|
|
60
|
+
this.ignoreBookSnapshotOverlapError = ignoreBookSnapshotOverlapError
|
|
61
|
+
}
|
|
47
62
|
|
|
48
63
|
canHandle(message: KucoinFuturesLevel2SnapshotMessage | KucoinFuturesLevel2UpdateMessage) {
|
|
49
64
|
return message.type === 'message' && message.topic.startsWith('/contractMarket/level2')
|
|
@@ -229,7 +244,7 @@ export class KucoinFuturesBookChangeMapper implements Mapper<'kucoin-futures', B
|
|
|
229
244
|
}
|
|
230
245
|
}
|
|
231
246
|
|
|
232
|
-
|
|
247
|
+
class KucoinFuturesBookTickerMapper implements Mapper<'kucoin-futures', BookTicker> {
|
|
233
248
|
canHandle(message: KucoinFuturesTickerMessage) {
|
|
234
249
|
return message.type === 'message' && message.topic.startsWith('/contractMarket/tickerV2')
|
|
235
250
|
}
|
|
@@ -267,7 +282,7 @@ export class KucoinFuturesBookTickerMapper implements Mapper<'kucoin-futures', B
|
|
|
267
282
|
}
|
|
268
283
|
}
|
|
269
284
|
|
|
270
|
-
|
|
285
|
+
class KucoinFuturesDerivativeTickerMapper implements Mapper<'kucoin-futures', DerivativeTicker> {
|
|
271
286
|
private readonly pendingTickerInfoHelper = new PendingTickerInfoHelper()
|
|
272
287
|
private readonly _lastPrices = new Map<string, number>()
|
|
273
288
|
private readonly _openInterests = new Map<string, number>()
|
package/src/mappers/lighter.ts
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import { asNonZeroNumberOrUndefined } from '../handy.ts'
|
|
2
2
|
import { BookChange, BookTicker, DerivativeTicker, Liquidation, Trade } from '../types.ts'
|
|
3
3
|
import { Mapper, PendingTickerInfoHelper } from './mapper.ts'
|
|
4
|
+
import { exchangeMappers } from './registry.ts'
|
|
5
|
+
|
|
6
|
+
export const lighterMappers = exchangeMappers({
|
|
7
|
+
lighter: {
|
|
8
|
+
trades: () => new LighterTradesMapper(),
|
|
9
|
+
bookChanges: () => new LighterBookChangeMapper(),
|
|
10
|
+
derivativeTickers: () => new LighterDerivativeTickerMapper(),
|
|
11
|
+
liquidations: () => new LighterLiquidationMapper(),
|
|
12
|
+
bookTickers: () => new LighterBookTickerMapper()
|
|
13
|
+
}
|
|
14
|
+
})
|
|
4
15
|
|
|
5
16
|
function parseChannelMarketId(channel: string): string | undefined {
|
|
6
17
|
const colonIndex = channel.indexOf(':')
|
|
@@ -14,7 +25,7 @@ function parseChannelMarketId(channel: string): string | undefined {
|
|
|
14
25
|
return suffix
|
|
15
26
|
}
|
|
16
27
|
|
|
17
|
-
|
|
28
|
+
class LighterTradesMapper implements Mapper<'lighter', Trade> {
|
|
18
29
|
canHandle(message: LighterTradeMessage) {
|
|
19
30
|
return message.type === 'update/trade'
|
|
20
31
|
}
|
|
@@ -45,7 +56,7 @@ export class LighterTradesMapper implements Mapper<'lighter', Trade> {
|
|
|
45
56
|
}
|
|
46
57
|
}
|
|
47
58
|
|
|
48
|
-
|
|
59
|
+
class LighterLiquidationMapper implements Mapper<'lighter', Liquidation> {
|
|
49
60
|
canHandle(message: LighterTradeMessage) {
|
|
50
61
|
return message.type === 'update/trade'
|
|
51
62
|
}
|
|
@@ -84,7 +95,7 @@ export class LighterLiquidationMapper implements Mapper<'lighter', Liquidation>
|
|
|
84
95
|
}
|
|
85
96
|
}
|
|
86
97
|
|
|
87
|
-
|
|
98
|
+
class LighterBookChangeMapper implements Mapper<'lighter', BookChange> {
|
|
88
99
|
canHandle(message: LighterOrderBookMessage) {
|
|
89
100
|
return message.type === 'subscribed/order_book' || message.type === 'update/order_book'
|
|
90
101
|
}
|
|
@@ -122,7 +133,7 @@ export class LighterBookChangeMapper implements Mapper<'lighter', BookChange> {
|
|
|
122
133
|
}
|
|
123
134
|
}
|
|
124
135
|
|
|
125
|
-
|
|
136
|
+
class LighterBookTickerMapper implements Mapper<'lighter', BookTicker> {
|
|
126
137
|
canHandle(message: LighterTickerMessage) {
|
|
127
138
|
return message.type === 'update/ticker'
|
|
128
139
|
}
|
|
@@ -154,7 +165,7 @@ export class LighterBookTickerMapper implements Mapper<'lighter', BookTicker> {
|
|
|
154
165
|
}
|
|
155
166
|
}
|
|
156
167
|
|
|
157
|
-
|
|
168
|
+
class LighterDerivativeTickerMapper implements Mapper<'lighter', DerivativeTicker> {
|
|
158
169
|
private readonly pendingTickerInfoHelper = new PendingTickerInfoHelper()
|
|
159
170
|
|
|
160
171
|
canHandle(message: LighterMarketStatsMessage) {
|
package/src/mappers/mapper.ts
CHANGED
|
@@ -8,7 +8,9 @@ export type Mapper<T extends Exchange, U extends NormalizedData> = {
|
|
|
8
8
|
getFilters: (symbols?: string[]) => FilterForExchange[T][]
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export type MapperFactory<T extends Exchange, U extends NormalizedData> = (exchange: T, localTimestamp: Date) => Mapper<T, U>
|
|
11
|
+
export type MapperFactory<T extends Exchange, U extends NormalizedData> = ((exchange: T, localTimestamp: Date) => Mapper<T, U>) & {
|
|
12
|
+
getSwitchDates?: (exchange: T) => readonly Date[]
|
|
13
|
+
}
|
|
12
14
|
|
|
13
15
|
type Writeable<T> = { -readonly [P in keyof T]: T[P] }
|
|
14
16
|
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
import { debug } from '../debug.ts'
|
|
2
|
+
import { asNumberOrUndefined, CircularBuffer, upperCaseSymbols } from '../handy.ts'
|
|
3
|
+
import { BookChange, BookPriceLevel, BookTicker, Trade } from '../types.ts'
|
|
4
|
+
import { Mapper } from './mapper.ts'
|
|
5
|
+
import { exchangeMappers, isRealTime } from './registry.ts'
|
|
6
|
+
|
|
7
|
+
export const mexcMappers = exchangeMappers({
|
|
8
|
+
mexc: {
|
|
9
|
+
trades: () => new MexcTradesMapper(),
|
|
10
|
+
bookChanges: (localTimestamp) => new MexcBookChangeMapper({ ignoreBookSnapshotOverlapError: isRealTime(localTimestamp) === false }),
|
|
11
|
+
bookTickers: () => new MexcBookTickerMapper()
|
|
12
|
+
}
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
export class MexcTradesMapper implements Mapper<'mexc', Trade> {
|
|
16
|
+
private readonly channel = 'spot@public.aggre.deals.v3.api.pb@10ms'
|
|
17
|
+
|
|
18
|
+
canHandle(message: MexcTradeMessage | MexcControlMessage) {
|
|
19
|
+
return message.channel?.startsWith(`${this.channel}@`) === true && 'publicAggreDeals' in message
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
getFilters(symbols?: string[]) {
|
|
23
|
+
return [{ channel: this.channel, symbols: upperCaseSymbols(symbols) } as const]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
*map(message: MexcTradeMessage, localTimestamp: Date): IterableIterator<Trade> {
|
|
27
|
+
for (const trade of message.publicAggreDeals.deals) {
|
|
28
|
+
yield {
|
|
29
|
+
type: 'trade',
|
|
30
|
+
symbol: message.symbol,
|
|
31
|
+
exchange: 'mexc',
|
|
32
|
+
id: trade.tradeId,
|
|
33
|
+
price: Number(trade.price),
|
|
34
|
+
amount: Number(trade.quantity),
|
|
35
|
+
side: trade.tradeType === MexcTradeType.Buy ? 'buy' : 'sell',
|
|
36
|
+
timestamp: new Date(Number(trade.time)),
|
|
37
|
+
localTimestamp
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export class MexcBookChangeMapper implements Mapper<'mexc', BookChange> {
|
|
44
|
+
private readonly channel = 'spot@public.aggre.depth.v3.api.pb@10ms'
|
|
45
|
+
private readonly snapshotChannel = 'spot@public.aggre.depth.snapshot.v3.api.pb@10ms'
|
|
46
|
+
private readonly symbolDepthInfo: Record<string, MexcDepthInfo> = {}
|
|
47
|
+
private readonly ignoreBookSnapshotOverlapError: boolean
|
|
48
|
+
|
|
49
|
+
constructor({ ignoreBookSnapshotOverlapError }: { ignoreBookSnapshotOverlapError: boolean }) {
|
|
50
|
+
this.ignoreBookSnapshotOverlapError = ignoreBookSnapshotOverlapError
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
canHandle(message: MexcDepthSnapshotMessage | MexcDepthUpdateMessage) {
|
|
54
|
+
return message.generated === true
|
|
55
|
+
? message.channel?.startsWith(`${this.snapshotChannel}@`) === true && 'publicAggreDepthsSnapshot' in message
|
|
56
|
+
: message.channel?.startsWith(`${this.channel}@`) === true && 'publicAggreDepths' in message
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
getFilters(symbols?: string[]) {
|
|
60
|
+
const normalizedSymbols = upperCaseSymbols(symbols)
|
|
61
|
+
|
|
62
|
+
return [
|
|
63
|
+
{ channel: this.channel, symbols: normalizedSymbols } as const,
|
|
64
|
+
{ channel: this.snapshotChannel, symbols: normalizedSymbols } as const
|
|
65
|
+
]
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
*map(message: MexcDepthSnapshotMessage | MexcDepthUpdateMessage, localTimestamp: Date): IterableIterator<BookChange> {
|
|
69
|
+
const depthInfo = this.getDepthInfoFor(message.symbol)
|
|
70
|
+
if (message.generated === true) {
|
|
71
|
+
if (depthInfo.snapshotEmitted) {
|
|
72
|
+
return
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
let currentBookVersion = Number(message.publicAggreDepthsSnapshot.lastUpdateId)
|
|
76
|
+
const bids = message.publicAggreDepthsSnapshot.bids.map(this.mapDepthSnapshotLevel)
|
|
77
|
+
const asks = message.publicAggreDepthsSnapshot.asks.map(this.mapDepthSnapshotLevel)
|
|
78
|
+
|
|
79
|
+
for (const update of depthInfo.updates.items()) {
|
|
80
|
+
const fromVersion = Number(update.publicAggreDepths.fromVersion)
|
|
81
|
+
const toVersion = Number(update.publicAggreDepths.toVersion)
|
|
82
|
+
if (currentBookVersion >= toVersion) {
|
|
83
|
+
continue
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (!depthInfo.isContinuityValidated) {
|
|
87
|
+
if (fromVersion > currentBookVersion + 1 || toVersion < currentBookVersion + 1) {
|
|
88
|
+
const message = `MEXC depth snapshot has no overlap with first update, update ${JSON.stringify(update)}, currentBookVersion: ${currentBookVersion}`
|
|
89
|
+
if (this.ignoreBookSnapshotOverlapError) {
|
|
90
|
+
depthInfo.isContinuityValidated = true
|
|
91
|
+
debug(message)
|
|
92
|
+
} else {
|
|
93
|
+
throw new Error(message)
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
depthInfo.isContinuityValidated = true
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
for (const bid of update.publicAggreDepths.bids ?? []) {
|
|
101
|
+
this.applyLevel(bids, this.mapBookLevel(bid))
|
|
102
|
+
}
|
|
103
|
+
for (const ask of update.publicAggreDepths.asks ?? []) {
|
|
104
|
+
this.applyLevel(asks, this.mapBookLevel(ask))
|
|
105
|
+
}
|
|
106
|
+
currentBookVersion = toVersion
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
depthInfo.updates.clear()
|
|
110
|
+
depthInfo.currentBookVersion = currentBookVersion
|
|
111
|
+
depthInfo.snapshotEmitted = true
|
|
112
|
+
|
|
113
|
+
yield {
|
|
114
|
+
type: 'book_change',
|
|
115
|
+
symbol: message.symbol,
|
|
116
|
+
exchange: 'mexc',
|
|
117
|
+
isSnapshot: true,
|
|
118
|
+
bids,
|
|
119
|
+
asks,
|
|
120
|
+
timestamp: new Date(Number(message.publicAggreDepthsSnapshot.timestamp)),
|
|
121
|
+
localTimestamp
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!depthInfo.snapshotEmitted) {
|
|
128
|
+
depthInfo.updates.append(message)
|
|
129
|
+
return
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const fromVersion = Number(message.publicAggreDepths.fromVersion)
|
|
133
|
+
const toVersion = Number(message.publicAggreDepths.toVersion)
|
|
134
|
+
if (toVersion <= depthInfo.currentBookVersion!) {
|
|
135
|
+
return
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (!depthInfo.isContinuityValidated) {
|
|
139
|
+
if (fromVersion > depthInfo.currentBookVersion! + 1 || toVersion < depthInfo.currentBookVersion! + 1) {
|
|
140
|
+
const errorMessage = `MEXC depth snapshot has no overlap with first update, update ${JSON.stringify(message)}, currentBookVersion: ${depthInfo.currentBookVersion}`
|
|
141
|
+
if (this.ignoreBookSnapshotOverlapError) {
|
|
142
|
+
depthInfo.isContinuityValidated = true
|
|
143
|
+
debug(errorMessage)
|
|
144
|
+
} else {
|
|
145
|
+
throw new Error(errorMessage)
|
|
146
|
+
}
|
|
147
|
+
} else {
|
|
148
|
+
depthInfo.isContinuityValidated = true
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
depthInfo.currentBookVersion = toVersion
|
|
153
|
+
|
|
154
|
+
yield {
|
|
155
|
+
type: 'book_change',
|
|
156
|
+
symbol: message.symbol,
|
|
157
|
+
exchange: 'mexc',
|
|
158
|
+
isSnapshot: false,
|
|
159
|
+
bids: (message.publicAggreDepths.bids ?? []).map(this.mapBookLevel),
|
|
160
|
+
asks: (message.publicAggreDepths.asks ?? []).map(this.mapBookLevel),
|
|
161
|
+
timestamp: new Date(Number(message.sendTime)),
|
|
162
|
+
localTimestamp
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
private applyLevel(bookSide: BookPriceLevel[], levelUpdate: BookPriceLevel) {
|
|
167
|
+
const existingIndex = bookSide.findIndex((level) => level.price === levelUpdate.price)
|
|
168
|
+
if (levelUpdate.amount === 0) {
|
|
169
|
+
if (existingIndex !== -1) {
|
|
170
|
+
bookSide.splice(existingIndex, 1)
|
|
171
|
+
}
|
|
172
|
+
return
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (existingIndex === -1) {
|
|
176
|
+
bookSide.push(levelUpdate)
|
|
177
|
+
} else {
|
|
178
|
+
bookSide[existingIndex] = levelUpdate
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
private mapBookLevel(level: MexcPriceLevel) {
|
|
183
|
+
return {
|
|
184
|
+
price: Number(level.price),
|
|
185
|
+
amount: Number(level.quantity)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
private mapDepthSnapshotLevel([price, quantity]: MexcDepthSnapshotLevel) {
|
|
190
|
+
return {
|
|
191
|
+
price: Number(price),
|
|
192
|
+
amount: Number(quantity)
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
private getDepthInfoFor(symbol: string) {
|
|
197
|
+
if (this.symbolDepthInfo[symbol] === undefined) {
|
|
198
|
+
this.symbolDepthInfo[symbol] = { updates: new CircularBuffer<MexcDepthUpdateMessage>(2000) }
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return this.symbolDepthInfo[symbol]
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export class MexcBookTickerMapper implements Mapper<'mexc', BookTicker> {
|
|
206
|
+
private readonly channel = 'spot@public.aggre.bookTicker.v3.api.pb@10ms'
|
|
207
|
+
|
|
208
|
+
canHandle(message: MexcBookTickerMessage | MexcControlMessage) {
|
|
209
|
+
return message.channel?.startsWith(`${this.channel}@`) === true && 'publicAggreBookTicker' in message
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
getFilters(symbols?: string[]) {
|
|
213
|
+
return [{ channel: this.channel, symbols: upperCaseSymbols(symbols) } as const]
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
*map(message: MexcBookTickerMessage, localTimestamp: Date): IterableIterator<BookTicker> {
|
|
217
|
+
yield {
|
|
218
|
+
type: 'book_ticker',
|
|
219
|
+
symbol: message.symbol,
|
|
220
|
+
exchange: 'mexc',
|
|
221
|
+
askAmount: asNumberOrUndefined(message.publicAggreBookTicker.askQuantity),
|
|
222
|
+
askPrice: asNumberOrUndefined(message.publicAggreBookTicker.askPrice),
|
|
223
|
+
bidAmount: asNumberOrUndefined(message.publicAggreBookTicker.bidQuantity),
|
|
224
|
+
bidPrice: asNumberOrUndefined(message.publicAggreBookTicker.bidPrice),
|
|
225
|
+
timestamp: new Date(Number(message.sendTime)),
|
|
226
|
+
localTimestamp
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
type MexcControlMessage = {
|
|
232
|
+
channel?: undefined
|
|
233
|
+
id?: number
|
|
234
|
+
code?: number
|
|
235
|
+
msg?: string
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
type MexcMappedChannel =
|
|
239
|
+
| 'spot@public.aggre.deals.v3.api.pb@10ms'
|
|
240
|
+
| 'spot@public.aggre.depth.v3.api.pb@10ms'
|
|
241
|
+
| 'spot@public.aggre.depth.snapshot.v3.api.pb@10ms'
|
|
242
|
+
| 'spot@public.aggre.bookTicker.v3.api.pb@10ms'
|
|
243
|
+
type MexcChannelWithSymbol<TChannel extends MexcMappedChannel> = `${TChannel}@${string}`
|
|
244
|
+
|
|
245
|
+
type MexcProtobufMessage<TChannel extends MexcMappedChannel> = {
|
|
246
|
+
channel: MexcChannelWithSymbol<TChannel>
|
|
247
|
+
symbol: string
|
|
248
|
+
symbolId?: string
|
|
249
|
+
createTime?: string | number
|
|
250
|
+
sendTime: string | number
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
type MexcTradeMessage = MexcProtobufMessage<'spot@public.aggre.deals.v3.api.pb@10ms'> & {
|
|
254
|
+
publicAggreDeals: {
|
|
255
|
+
eventType: 'spot@public.aggre.deals.v3.api.pb@10ms'
|
|
256
|
+
deals: MexcTrade[]
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
type MexcTrade = {
|
|
261
|
+
price: string
|
|
262
|
+
quantity: string
|
|
263
|
+
tradeType: MexcTradeType
|
|
264
|
+
time: string | number
|
|
265
|
+
tradeId?: string
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
enum MexcTradeType {
|
|
269
|
+
Buy = 1,
|
|
270
|
+
Sell = 2
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export type MexcDepthSnapshotMessage = {
|
|
274
|
+
channel: MexcChannelWithSymbol<'spot@public.aggre.depth.snapshot.v3.api.pb@10ms'>
|
|
275
|
+
symbol: string
|
|
276
|
+
generated: true
|
|
277
|
+
publicAggreDepthsSnapshot: MexcAggreDepthsSnapshot
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
type MexcAggreDepthsSnapshot = {
|
|
281
|
+
asks: MexcDepthSnapshotLevel[]
|
|
282
|
+
bids: MexcDepthSnapshotLevel[]
|
|
283
|
+
lastUpdateId: number
|
|
284
|
+
timestamp: number
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
type MexcDepthSnapshotLevel = [string, string]
|
|
288
|
+
|
|
289
|
+
type MexcDepthUpdateMessage = MexcProtobufMessage<'spot@public.aggre.depth.v3.api.pb@10ms'> & {
|
|
290
|
+
generated?: undefined
|
|
291
|
+
publicAggreDepths: MexcAggreDepths
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
type MexcAggreDepths = {
|
|
295
|
+
eventType: 'spot@public.aggre.depth.v3.api.pb@10ms'
|
|
296
|
+
asks?: MexcPriceLevel[]
|
|
297
|
+
bids?: MexcPriceLevel[]
|
|
298
|
+
fromVersion: string
|
|
299
|
+
toVersion: string
|
|
300
|
+
lastOrderCreateTime?: string | number
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
type MexcPriceLevel = {
|
|
304
|
+
price: string
|
|
305
|
+
quantity: string
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
type MexcBookTickerMessage = MexcProtobufMessage<'spot@public.aggre.bookTicker.v3.api.pb@10ms'> & {
|
|
309
|
+
publicAggreBookTicker: {
|
|
310
|
+
bidPrice?: string
|
|
311
|
+
bidQuantity?: string
|
|
312
|
+
askPrice?: string
|
|
313
|
+
askQuantity?: string
|
|
314
|
+
version?: string
|
|
315
|
+
lastOrderCreateTime?: string | number
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
type MexcDepthInfo = {
|
|
320
|
+
isContinuityValidated?: boolean
|
|
321
|
+
currentBookVersion?: number
|
|
322
|
+
snapshotEmitted?: boolean
|
|
323
|
+
updates: CircularBuffer<MexcDepthUpdateMessage>
|
|
324
|
+
}
|