tardis-dev 15.3.2 → 16.1.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 +2 -1
- package/dist/consts.d.ts.map +1 -1
- package/dist/consts.js +5 -2
- package/dist/consts.js.map +1 -1
- package/dist/mappers/bybit.d.ts +2 -2
- package/dist/mappers/bybitspot.d.ts +1 -1
- package/dist/mappers/cryptocom.d.ts +1 -1
- package/dist/mappers/huobi.d.ts +3 -3
- package/dist/mappers/index.d.ts +6 -0
- package/dist/mappers/index.d.ts.map +1 -1
- package/dist/mappers/index.js +9 -3
- package/dist/mappers/index.js.map +1 -1
- package/dist/mappers/lighter.d.ts +159 -0
- package/dist/mappers/lighter.d.ts.map +1 -0
- package/dist/mappers/lighter.js +173 -0
- package/dist/mappers/lighter.js.map +1 -0
- package/dist/options.d.ts +2 -0
- package/dist/options.d.ts.map +1 -1
- package/dist/options.js +1 -0
- package/dist/options.js.map +1 -1
- package/dist/realtimefeeds/index.d.ts.map +1 -1
- package/dist/realtimefeeds/index.js +3 -1
- package/dist/realtimefeeds/index.js.map +1 -1
- package/dist/realtimefeeds/lighter.d.ts +8 -0
- package/dist/realtimefeeds/lighter.d.ts.map +1 -0
- package/dist/realtimefeeds/lighter.js +25 -0
- package/dist/realtimefeeds/lighter.js.map +1 -0
- package/dist/replay.d.ts.map +1 -1
- package/dist/replay.js +1 -0
- package/dist/replay.js.map +1 -1
- package/dist/worker.d.ts +2 -0
- package/dist/worker.d.ts.map +1 -1
- package/dist/worker.js +4 -5
- package/dist/worker.js.map +1 -1
- package/package.json +2 -2
- package/src/consts.ts +6 -2
- package/src/mappers/index.ts +15 -3
- package/src/mappers/lighter.ts +348 -0
- package/src/options.ts +4 -0
- package/src/realtimefeeds/index.ts +3 -1
- package/src/realtimefeeds/lighter.ts +31 -0
- package/src/replay.ts +1 -0
- package/src/worker.ts +6 -5
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
import { asNumberIfValid } from '../handy.ts'
|
|
2
|
+
import { BookChange, BookTicker, DerivativeTicker, Liquidation, Trade } from '../types.ts'
|
|
3
|
+
import { Mapper, PendingTickerInfoHelper } from './mapper.ts'
|
|
4
|
+
|
|
5
|
+
function parseChannelMarketId(channel: string): string | undefined {
|
|
6
|
+
const colonIndex = channel.indexOf(':')
|
|
7
|
+
if (colonIndex < 0) {
|
|
8
|
+
return undefined
|
|
9
|
+
}
|
|
10
|
+
const suffix = channel.slice(colonIndex + 1)
|
|
11
|
+
if (suffix === 'all') {
|
|
12
|
+
return undefined
|
|
13
|
+
}
|
|
14
|
+
return suffix
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class LighterTradesMapper implements Mapper<'lighter', Trade> {
|
|
18
|
+
canHandle(message: LighterTradeMessage) {
|
|
19
|
+
return message.type === 'update/trade'
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
getFilters(symbols?: string[]) {
|
|
23
|
+
return [
|
|
24
|
+
{
|
|
25
|
+
channel: 'trade' as const,
|
|
26
|
+
symbols
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
*map(message: LighterTradeMessage, localTimestamp: Date): IterableIterator<Trade> {
|
|
32
|
+
for (const trade of message.trades) {
|
|
33
|
+
yield {
|
|
34
|
+
type: 'trade',
|
|
35
|
+
symbol: trade.market_id.toString(),
|
|
36
|
+
exchange: 'lighter',
|
|
37
|
+
id: trade.trade_id_str,
|
|
38
|
+
price: Number(trade.price),
|
|
39
|
+
amount: Number(trade.size),
|
|
40
|
+
side: trade.is_maker_ask ? 'buy' : 'sell',
|
|
41
|
+
timestamp: new Date(trade.timestamp),
|
|
42
|
+
localTimestamp
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export class LighterLiquidationMapper implements Mapper<'lighter', Liquidation> {
|
|
49
|
+
canHandle(message: LighterTradeMessage) {
|
|
50
|
+
return message.type === 'update/trade'
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
getFilters(symbols?: string[]) {
|
|
54
|
+
return [
|
|
55
|
+
{
|
|
56
|
+
channel: 'trade' as const,
|
|
57
|
+
symbols
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
*map(message: LighterTradeMessage, localTimestamp: Date): IterableIterator<Liquidation> {
|
|
63
|
+
for (const trade of message.liquidation_trades) {
|
|
64
|
+
if (trade.type !== 'liquidation') {
|
|
65
|
+
continue
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
yield {
|
|
69
|
+
type: 'liquidation',
|
|
70
|
+
symbol: trade.market_id.toString(),
|
|
71
|
+
exchange: 'lighter',
|
|
72
|
+
id: trade.trade_id_str,
|
|
73
|
+
price: Number(trade.price),
|
|
74
|
+
amount: Number(trade.size),
|
|
75
|
+
side: trade.is_maker_ask ? 'buy' : 'sell',
|
|
76
|
+
timestamp: new Date(trade.timestamp),
|
|
77
|
+
localTimestamp
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export class LighterBookChangeMapper implements Mapper<'lighter', BookChange> {
|
|
84
|
+
canHandle(message: LighterOrderBookMessage) {
|
|
85
|
+
return message.type === 'subscribed/order_book' || message.type === 'update/order_book'
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
getFilters(symbols?: string[]) {
|
|
89
|
+
return [
|
|
90
|
+
{
|
|
91
|
+
channel: 'order_book' as const,
|
|
92
|
+
symbols
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
*map(message: LighterOrderBookMessage, localTimestamp: Date): IterableIterator<BookChange> {
|
|
98
|
+
const symbol = parseChannelMarketId(message.channel)
|
|
99
|
+
if (symbol === undefined) return
|
|
100
|
+
|
|
101
|
+
yield {
|
|
102
|
+
type: 'book_change',
|
|
103
|
+
symbol,
|
|
104
|
+
exchange: 'lighter',
|
|
105
|
+
isSnapshot: message.type === 'subscribed/order_book',
|
|
106
|
+
bids: message.order_book.bids.map(this.mapLevel),
|
|
107
|
+
asks: message.order_book.asks.map(this.mapLevel),
|
|
108
|
+
timestamp: new Date(message.timestamp),
|
|
109
|
+
localTimestamp
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private mapLevel(level: LighterLevel) {
|
|
114
|
+
return {
|
|
115
|
+
price: Number(level.price),
|
|
116
|
+
amount: Number(level.size)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export class LighterBookTickerMapper implements Mapper<'lighter', BookTicker> {
|
|
122
|
+
canHandle(message: LighterTickerMessage) {
|
|
123
|
+
return message.type === 'update/ticker'
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
getFilters(symbols?: string[]) {
|
|
127
|
+
return [
|
|
128
|
+
{
|
|
129
|
+
channel: 'ticker' as const,
|
|
130
|
+
symbols
|
|
131
|
+
}
|
|
132
|
+
]
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
*map(message: LighterTickerMessage, localTimestamp: Date): IterableIterator<BookTicker> {
|
|
136
|
+
const symbol = parseChannelMarketId(message.channel)
|
|
137
|
+
if (symbol === undefined) return
|
|
138
|
+
|
|
139
|
+
yield {
|
|
140
|
+
type: 'book_ticker',
|
|
141
|
+
symbol,
|
|
142
|
+
exchange: 'lighter',
|
|
143
|
+
askAmount: asNumberIfValid(message.ticker?.a?.size),
|
|
144
|
+
askPrice: asNumberIfValid(message.ticker?.a?.price),
|
|
145
|
+
bidPrice: asNumberIfValid(message.ticker?.b?.price),
|
|
146
|
+
bidAmount: asNumberIfValid(message.ticker?.b?.size),
|
|
147
|
+
timestamp: new Date(message.timestamp),
|
|
148
|
+
localTimestamp
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export class LighterDerivativeTickerMapper implements Mapper<'lighter', DerivativeTicker> {
|
|
154
|
+
private readonly pendingTickerInfoHelper = new PendingTickerInfoHelper()
|
|
155
|
+
|
|
156
|
+
canHandle(message: LighterMarketStatsMessage) {
|
|
157
|
+
return message.type === 'update/market_stats'
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
getFilters(_symbols?: string[]) {
|
|
161
|
+
return [
|
|
162
|
+
{
|
|
163
|
+
channel: 'market_stats' as const,
|
|
164
|
+
symbols: []
|
|
165
|
+
}
|
|
166
|
+
]
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
*map(message: LighterMarketStatsMessage, localTimestamp: Date): IterableIterator<DerivativeTicker> {
|
|
170
|
+
for (const entry of this.iterateMarketStats(message)) {
|
|
171
|
+
const pendingTickerInfo = this.pendingTickerInfoHelper.getPendingTickerInfo(entry.market_id.toString(), 'lighter')
|
|
172
|
+
|
|
173
|
+
pendingTickerInfo.updateMarkPrice(Number(entry.mark_price))
|
|
174
|
+
pendingTickerInfo.updateIndexPrice(Number(entry.index_price))
|
|
175
|
+
pendingTickerInfo.updateFundingRate(Number(entry.current_funding_rate))
|
|
176
|
+
pendingTickerInfo.updateLastPrice(Number(entry.last_trade_price))
|
|
177
|
+
pendingTickerInfo.updateOpenInterest(Number(entry.open_interest))
|
|
178
|
+
|
|
179
|
+
if (pendingTickerInfo.hasChanged()) {
|
|
180
|
+
pendingTickerInfo.updateTimestamp(new Date(message.timestamp))
|
|
181
|
+
yield pendingTickerInfo.getSnapshot(localTimestamp)
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private *iterateMarketStats(message: LighterMarketStatsMessage): IterableIterator<LighterMarketStats> {
|
|
187
|
+
if (message.channel === 'market_stats:all') {
|
|
188
|
+
for (const key of Object.keys(message.market_stats)) {
|
|
189
|
+
yield message.market_stats[key]
|
|
190
|
+
}
|
|
191
|
+
return
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
yield message.market_stats
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
type LighterLevel = {
|
|
199
|
+
price: string
|
|
200
|
+
size: string
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
type LighterOrderBook = {
|
|
204
|
+
asks: LighterLevel[]
|
|
205
|
+
bids: LighterLevel[]
|
|
206
|
+
code: number
|
|
207
|
+
nonce: number
|
|
208
|
+
begin_nonce: number
|
|
209
|
+
offset: number
|
|
210
|
+
last_updated_at: number
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
type LighterOrderBookMessage = {
|
|
214
|
+
type: 'subscribed/order_book' | 'update/order_book'
|
|
215
|
+
channel: `order_book:${number}`
|
|
216
|
+
last_updated_at: number
|
|
217
|
+
offset: number
|
|
218
|
+
timestamp: number
|
|
219
|
+
order_book: LighterOrderBook
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
type LighterTicker = {
|
|
223
|
+
s: string
|
|
224
|
+
a?: Partial<LighterLevel>
|
|
225
|
+
b?: Partial<LighterLevel>
|
|
226
|
+
last_updated_at: number
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
type LighterTickerMessage = {
|
|
230
|
+
type: 'subscribed/ticker' | 'update/ticker'
|
|
231
|
+
channel: `ticker:${number}`
|
|
232
|
+
last_updated_at: number
|
|
233
|
+
nonce: number
|
|
234
|
+
ticker: LighterTicker
|
|
235
|
+
timestamp: number
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
type LighterTrade = {
|
|
239
|
+
trade_id: number
|
|
240
|
+
trade_id_str: string
|
|
241
|
+
tx_hash: string
|
|
242
|
+
type: 'trade' | 'liquidation' | 'deleverage' | 'market-settlement'
|
|
243
|
+
market_id: number
|
|
244
|
+
size: string
|
|
245
|
+
price: string
|
|
246
|
+
usd_amount: string
|
|
247
|
+
ask_id: number
|
|
248
|
+
ask_id_str: string
|
|
249
|
+
bid_id: number
|
|
250
|
+
bid_id_str: string
|
|
251
|
+
ask_client_id: number
|
|
252
|
+
ask_client_id_str: string
|
|
253
|
+
bid_client_id: number
|
|
254
|
+
bid_client_id_str: string
|
|
255
|
+
ask_account_id: number
|
|
256
|
+
bid_account_id: number
|
|
257
|
+
is_maker_ask: boolean
|
|
258
|
+
block_height: number
|
|
259
|
+
timestamp: number
|
|
260
|
+
taker_fee?: number
|
|
261
|
+
taker_position_size_before?: string
|
|
262
|
+
taker_entry_quote_before?: string
|
|
263
|
+
taker_initial_margin_fraction_before?: number
|
|
264
|
+
taker_position_sign_changed?: boolean
|
|
265
|
+
taker_allocated_margin_usdc_before?: number
|
|
266
|
+
maker_fee?: number
|
|
267
|
+
maker_position_size_before?: string
|
|
268
|
+
maker_entry_quote_before?: string
|
|
269
|
+
maker_initial_margin_fraction_before?: number
|
|
270
|
+
maker_position_sign_changed?: boolean
|
|
271
|
+
transaction_time: number
|
|
272
|
+
ask_account_pnl?: string
|
|
273
|
+
bid_account_pnl?: string
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
type LighterTradeMessage = {
|
|
277
|
+
type: 'subscribed/trade' | 'update/trade'
|
|
278
|
+
channel: `trade:${number}`
|
|
279
|
+
nonce: number
|
|
280
|
+
trades: LighterTrade[]
|
|
281
|
+
liquidation_trades: LighterTrade[]
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
type LighterMarketStats = {
|
|
285
|
+
symbol: string
|
|
286
|
+
market_id: number
|
|
287
|
+
index_price: string
|
|
288
|
+
mark_price: string
|
|
289
|
+
mid_price: string
|
|
290
|
+
open_interest: string
|
|
291
|
+
open_interest_limit: string
|
|
292
|
+
funding_clamp_small: string
|
|
293
|
+
funding_clamp_big: string
|
|
294
|
+
last_trade_price: string
|
|
295
|
+
current_funding_rate: string
|
|
296
|
+
funding_rate: string
|
|
297
|
+
funding_timestamp: number
|
|
298
|
+
daily_base_token_volume: number
|
|
299
|
+
daily_quote_token_volume: number
|
|
300
|
+
daily_price_low: number
|
|
301
|
+
daily_price_high: number
|
|
302
|
+
daily_price_change: number
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
type LighterMarketStatsAllMessage = {
|
|
306
|
+
type: 'subscribed/market_stats' | 'update/market_stats'
|
|
307
|
+
channel: 'market_stats:all'
|
|
308
|
+
timestamp: number
|
|
309
|
+
market_stats: Record<string, LighterMarketStats>
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
type LighterMarketStatsMarketIdMessage = {
|
|
313
|
+
type: 'subscribed/market_stats' | 'update/market_stats'
|
|
314
|
+
channel: `market_stats:${number}`
|
|
315
|
+
timestamp: number
|
|
316
|
+
market_stats: LighterMarketStats
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
type LighterMarketStatsMessage = LighterMarketStatsAllMessage | LighterMarketStatsMarketIdMessage
|
|
320
|
+
|
|
321
|
+
type LighterSpotMarketStats = {
|
|
322
|
+
symbol: string
|
|
323
|
+
market_id: number
|
|
324
|
+
index_price: string
|
|
325
|
+
mid_price: string
|
|
326
|
+
last_trade_price: string
|
|
327
|
+
daily_base_token_volume: number
|
|
328
|
+
daily_quote_token_volume: number
|
|
329
|
+
daily_price_low: number
|
|
330
|
+
daily_price_high: number
|
|
331
|
+
daily_price_change: number
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
type LighterSpotMarketStatsAllMessage = {
|
|
335
|
+
type: 'subscribed/spot_market_stats' | 'update/spot_market_stats'
|
|
336
|
+
channel: 'spot_market_stats:all'
|
|
337
|
+
timestamp: number
|
|
338
|
+
spot_market_stats: Record<string, LighterSpotMarketStats>
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
type LighterSpotMarketStatsMarketIdMessage = {
|
|
342
|
+
type: 'subscribed/spot_market_stats' | 'update/spot_market_stats'
|
|
343
|
+
channel: `spot_market_stats:${number}`
|
|
344
|
+
timestamp: number
|
|
345
|
+
spot_market_stats: LighterSpotMarketStats
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
type LighterSpotMarketStatsMessage = LighterSpotMarketStatsAllMessage | LighterSpotMarketStatsMarketIdMessage
|
package/src/options.ts
CHANGED
|
@@ -10,6 +10,7 @@ const defaultOptions: Options = {
|
|
|
10
10
|
datasetsEndpoint: 'https://datasets.tardis.dev/v1',
|
|
11
11
|
cacheDir: path.join(os.tmpdir(), '.tardis-cache'),
|
|
12
12
|
apiKey: '',
|
|
13
|
+
dataFeedCompression: 'zstd',
|
|
13
14
|
_userAgent: `tardis-dev/${packageJson.version} (+https://github.com/tardis-dev/tardis-node)`
|
|
14
15
|
}
|
|
15
16
|
|
|
@@ -28,5 +29,8 @@ type Options = {
|
|
|
28
29
|
datasetsEndpoint: string
|
|
29
30
|
cacheDir: string
|
|
30
31
|
apiKey: string
|
|
32
|
+
dataFeedCompression: DataFeedCompression
|
|
31
33
|
_userAgent: string
|
|
32
34
|
}
|
|
35
|
+
|
|
36
|
+
export type DataFeedCompression = 'gzip' | 'zstd'
|
|
@@ -52,6 +52,7 @@ import { DydxV4RealTimeFeed } from './dydx_v4.ts'
|
|
|
52
52
|
import { BitgetFuturesRealTimeFeed, BitgetRealTimeFeed } from './bitget.ts'
|
|
53
53
|
import { CoinbaseInternationalRealTimeFeed } from './coinbaseinternational.ts'
|
|
54
54
|
import { HyperliquidRealTimeFeed } from './hyperliquid.ts'
|
|
55
|
+
import { LighterRealTimeFeed } from './lighter.ts'
|
|
55
56
|
|
|
56
57
|
export * from './realtimefeed.ts'
|
|
57
58
|
|
|
@@ -114,7 +115,8 @@ const realTimeFeedsMap: {
|
|
|
114
115
|
bitget: BitgetRealTimeFeed,
|
|
115
116
|
'bitget-futures': BitgetFuturesRealTimeFeed,
|
|
116
117
|
'coinbase-international': CoinbaseInternationalRealTimeFeed,
|
|
117
|
-
hyperliquid: HyperliquidRealTimeFeed
|
|
118
|
+
hyperliquid: HyperliquidRealTimeFeed,
|
|
119
|
+
lighter: LighterRealTimeFeed
|
|
118
120
|
}
|
|
119
121
|
|
|
120
122
|
export function getRealTimeFeedFactory(exchange: Exchange): RealTimeFeed {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Filter } from '../types.ts'
|
|
2
|
+
import { RealTimeFeedBase } from './realtimefeed.ts'
|
|
3
|
+
|
|
4
|
+
export class LighterRealTimeFeed extends RealTimeFeedBase {
|
|
5
|
+
protected wssURL = 'wss://mainnet.zklighter.elliot.ai/stream'
|
|
6
|
+
|
|
7
|
+
protected mapToSubscribeMessages(filters: Filter<string>[]): any[] {
|
|
8
|
+
return filters.flatMap((filter) => {
|
|
9
|
+
if (filter.channel === 'market_stats') {
|
|
10
|
+
return [{ type: 'subscribe', channel: 'market_stats/all' }]
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (filter.channel === 'spot_market_stats') {
|
|
14
|
+
return [{ type: 'subscribe', channel: 'spot_market_stats/all' }]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (!filter.symbols || filter.symbols.length === 0) {
|
|
18
|
+
throw new Error('LighterRealTimeFeed requires explicitly specified symbols when subscribing to live feed')
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return filter.symbols.map((marketId) => ({
|
|
22
|
+
type: 'subscribe',
|
|
23
|
+
channel: `${filter.channel}/${marketId}`
|
|
24
|
+
}))
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
protected messageIsError(message: any): boolean {
|
|
29
|
+
return message.error !== undefined
|
|
30
|
+
}
|
|
31
|
+
}
|
package/src/replay.ts
CHANGED
|
@@ -53,6 +53,7 @@ export async function* replay<T extends Exchange, U extends boolean = false, Z e
|
|
|
53
53
|
cacheDir: options.cacheDir,
|
|
54
54
|
endpoint: options.endpoint,
|
|
55
55
|
apiKey: apiKey || options.apiKey,
|
|
56
|
+
dataFeedCompression: options.dataFeedCompression,
|
|
56
57
|
userAgent: options._userAgent,
|
|
57
58
|
fromDate,
|
|
58
59
|
toDate,
|
package/src/worker.ts
CHANGED
|
@@ -3,12 +3,12 @@ import { existsSync } from 'node:fs'
|
|
|
3
3
|
import pMap from 'p-map'
|
|
4
4
|
import { isMainThread, parentPort, workerData } from 'worker_threads'
|
|
5
5
|
import { addMinutes, download, formatDateToPath, optimizeFilters, sequence, sha256, wait, cleanTempFiles } from './handy.ts'
|
|
6
|
+
import type { DataFeedCompression } from './options.ts'
|
|
6
7
|
import { Exchange, Filter } from './types.ts'
|
|
7
8
|
const debug = dbg('tardis-dev')
|
|
8
|
-
const ACCEPT_ENCODING = 'zstd, gzip'
|
|
9
9
|
|
|
10
10
|
if (isMainThread) {
|
|
11
|
-
debug('
|
|
11
|
+
debug('current worker is not meant to run in main thread')
|
|
12
12
|
} else {
|
|
13
13
|
parentPort!.on('message', (signal: WorkerSignal) => {
|
|
14
14
|
if (signal === WorkerSignal.BEFORE_TERMINATE) {
|
|
@@ -92,7 +92,7 @@ async function getDataFeedSlices(payload: WorkerJobPayload) {
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
async function getDataFeedSlice(
|
|
95
|
-
{ exchange, fromDate, endpoint, apiKey, userAgent }: WorkerJobPayload,
|
|
95
|
+
{ exchange, fromDate, endpoint, apiKey, dataFeedCompression, userAgent }: WorkerJobPayload,
|
|
96
96
|
offset: number,
|
|
97
97
|
filters: object[],
|
|
98
98
|
cacheDir: string
|
|
@@ -104,7 +104,7 @@ async function getDataFeedSlice(
|
|
|
104
104
|
const gzipSlicePath = `${sliceBasePath}.gz`
|
|
105
105
|
const cachedSlicePath = existsSync(zstdSlicePath) ? zstdSlicePath : existsSync(gzipSlicePath) ? gzipSlicePath : undefined
|
|
106
106
|
|
|
107
|
-
let url = `${endpoint}/data-feeds/${exchange}?from=${fromDate.toISOString()}&offset=${offset}`
|
|
107
|
+
let url = `${endpoint}/data-feeds/${exchange}?from=${fromDate.toISOString()}&offset=${offset}&compression=${dataFeedCompression}`
|
|
108
108
|
|
|
109
109
|
if (filters.length > 0) {
|
|
110
110
|
url += `&filters=${encodeURIComponent(JSON.stringify(filters))}`
|
|
@@ -119,7 +119,7 @@ async function getDataFeedSlice(
|
|
|
119
119
|
url,
|
|
120
120
|
userAgent,
|
|
121
121
|
appendContentEncodingExtension: true,
|
|
122
|
-
acceptEncoding:
|
|
122
|
+
acceptEncoding: dataFeedCompression === 'gzip' ? 'gzip' : 'zstd, gzip'
|
|
123
123
|
})
|
|
124
124
|
).downloadPath
|
|
125
125
|
|
|
@@ -146,6 +146,7 @@ export type WorkerJobPayload = {
|
|
|
146
146
|
cacheDir: string
|
|
147
147
|
endpoint: string
|
|
148
148
|
apiKey: string
|
|
149
|
+
dataFeedCompression: DataFeedCompression
|
|
149
150
|
userAgent: string
|
|
150
151
|
fromDate: Date
|
|
151
152
|
toDate: Date
|