unicex 0.8.1__py3-none-any.whl → 0.10.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. unicex/_abc/__init__.py +0 -2
  2. unicex/_base/websocket.py +26 -18
  3. unicex/bitget/websocket_manager.py +6 -6
  4. unicex/bybit/websocket_manager.py +10 -10
  5. unicex/gateio/websocket_manager.py +503 -1
  6. unicex/hyperliquid/adapter.py +1 -1
  7. unicex/hyperliquid/websocket_manager.py +353 -1
  8. unicex/mexc/_spot_ws_proto/PrivateAccountV3Api_pb2.py +0 -2
  9. unicex/mexc/_spot_ws_proto/PrivateDealsV3Api_pb2.py +0 -2
  10. unicex/mexc/_spot_ws_proto/PrivateOrdersV3Api_pb2.py +0 -2
  11. unicex/mexc/_spot_ws_proto/PublicAggreBookTickerV3Api_pb2.py +0 -2
  12. unicex/mexc/_spot_ws_proto/PublicAggreDealsV3Api_pb2.py +0 -2
  13. unicex/mexc/_spot_ws_proto/PublicAggreDepthsV3Api_pb2.py +0 -2
  14. unicex/mexc/_spot_ws_proto/PublicBookTickerBatchV3Api_pb2.py +0 -2
  15. unicex/mexc/_spot_ws_proto/PublicBookTickerV3Api_pb2.py +0 -2
  16. unicex/mexc/_spot_ws_proto/PublicDealsV3Api_pb2.py +0 -2
  17. unicex/mexc/_spot_ws_proto/PublicFuture_pb2.py +0 -2
  18. unicex/mexc/_spot_ws_proto/PublicIncreaseDepthsBatchV3Api_pb2.py +0 -2
  19. unicex/mexc/_spot_ws_proto/PublicIncreaseDepthsV3Api_pb2.py +0 -2
  20. unicex/mexc/_spot_ws_proto/PublicLimitDepthsV3Api_pb2.py +0 -2
  21. unicex/mexc/_spot_ws_proto/PublicMiniTickerV3Api_pb2.py +0 -2
  22. unicex/mexc/_spot_ws_proto/PublicMiniTickersV3Api_pb2.py +0 -2
  23. unicex/mexc/_spot_ws_proto/PublicSpotKlineV3Api_pb2.py +0 -2
  24. unicex/mexc/_spot_ws_proto/PushDataV3ApiWrapper_pb2.py +0 -2
  25. unicex/mexc/_spot_ws_proto/__init__.py +335 -332
  26. unicex/mexc/websocket_manager.py +447 -2
  27. unicex/okx/websocket_manager.py +733 -1
  28. {unicex-0.8.1.dist-info → unicex-0.10.1.dist-info}/METADATA +5 -5
  29. {unicex-0.8.1.dist-info → unicex-0.10.1.dist-info}/RECORD +32 -33
  30. unicex/_abc/decoder.py +0 -18
  31. {unicex-0.8.1.dist-info → unicex-0.10.1.dist-info}/WHEEL +0 -0
  32. {unicex-0.8.1.dist-info → unicex-0.10.1.dist-info}/licenses/LICENSE +0 -0
  33. {unicex-0.8.1.dist-info → unicex-0.10.1.dist-info}/top_level.txt +0 -0
@@ -1,11 +1,456 @@
1
1
  __all__ = ["WebsocketManager"]
2
2
 
3
+ import json
4
+ from collections.abc import Awaitable, Callable, Sequence
5
+ from typing import Any, Literal
3
6
 
4
- from collections.abc import Awaitable, Callable
5
- from typing import Any
7
+ import orjson
8
+ from google.protobuf.json_format import MessageToDict
9
+
10
+ from unicex._base import Websocket
11
+
12
+ from ._spot_ws_proto import PushDataV3ApiWrapper
13
+ from .client import Client
6
14
 
7
15
  type CallbackType = Callable[[Any], Awaitable[None]]
8
16
 
9
17
 
10
18
  class WebsocketManager:
11
19
  """Менеджер асинхронных вебсокетов для Mexc."""
20
+
21
+ _SPOT_URL: str = "wss://wbs-api.mexc.com/ws"
22
+ """Базовый URL для вебсокета на спот."""
23
+
24
+ _FUTURES_URL: str = "wss://contract.mexc.com/edge"
25
+ """Базовый URL для вебсокета на фьючерсы."""
26
+
27
+ class _MexcProtobufDecoder:
28
+ """Класс для декодирования сообщений в формате Protobuf со спотового рынка Mexc."""
29
+
30
+ def decode(self, message: Any) -> dict:
31
+ if isinstance(message, bytes):
32
+ wrapper = PushDataV3ApiWrapper() # noqa
33
+ wrapper.ParseFromString(message)
34
+ return MessageToDict(wrapper, preserving_proto_field_name=True) # type: ignore
35
+ elif isinstance(message, str):
36
+ return orjson.loads(message)
37
+ else:
38
+ raise ValueError(f"Invalid message type: {type(message)}")
39
+
40
+ def __init__(self, client: Client | None = None, **ws_kwargs: Any) -> None:
41
+ """Инициализирует менеджер вебсокетов для Mexc.
42
+
43
+ Параметры:
44
+ client (`Client | None`): Клиент для выполнения запросов. Нужен, чтобы открыть приватные вебсокеты.
45
+ ws_kwargs (`dict[str, Any]`): Дополнительные аргументы, которые прокидываются в `Websocket`.
46
+ """
47
+ self.client = client
48
+ self._ws_kwargs = ws_kwargs
49
+
50
+ def _generate_subscription_message(
51
+ self,
52
+ channel_template: str,
53
+ symbol: str | None = None,
54
+ symbols: Sequence[str] | None = None,
55
+ **template_kwargs: Any,
56
+ ) -> list[str]:
57
+ """Сформировать сообщение для подписки на вебсокет."""
58
+ if symbol and symbols:
59
+ raise ValueError("Parameters symbol and symbols cannot be used together")
60
+ if not (symbol or symbols):
61
+ raise ValueError("Either symbol or symbols must be provided")
62
+
63
+ if symbol:
64
+ params = [channel_template.format(symbol=symbol, **template_kwargs)]
65
+ elif symbols:
66
+ params = [
67
+ channel_template.format(symbol=symbol, **template_kwargs) for symbol in symbols
68
+ ]
69
+
70
+ return [json.dumps({"method": "SUBSCRIPTION", "params": params})]
71
+
72
+ def _generate_futures_subscription_message(
73
+ self,
74
+ topic: str,
75
+ symbol: str | None = None,
76
+ symbols: Sequence[str] | None = None,
77
+ require_symbol: bool = True,
78
+ **additional_params_kwargs: Any,
79
+ ) -> list[str]:
80
+ """Сформировать сообщение для подписки на фьючерсный вебсокет."""
81
+ if symbol and symbols:
82
+ raise ValueError("Parameters symbol and symbols cannot be used together")
83
+ if require_symbol and not (symbol or symbols):
84
+ raise ValueError("Either symbol or symbols must be provided")
85
+
86
+ if symbol:
87
+ symbols = [symbol]
88
+ if symbols:
89
+ return [
90
+ json.dumps({"method": topic, "param": {"symbol": s, **additional_params_kwargs}})
91
+ for s in symbols
92
+ ] # type: ignore
93
+ return [json.dumps({"method": topic, "param": {**additional_params_kwargs}})]
94
+
95
+ def _create_websocket(
96
+ self, callback: CallbackType, subscription_messages: list[str]
97
+ ) -> Websocket:
98
+ """Шорткат для создания вебсокета."""
99
+ return Websocket(
100
+ callback=callback,
101
+ url=self._SPOT_URL,
102
+ subscription_messages=subscription_messages,
103
+ decoder=self._MexcProtobufDecoder,
104
+ ping_message='{"method": "PING"}',
105
+ **self._ws_kwargs,
106
+ )
107
+
108
+ def _create_futures_websocket(
109
+ self, callback: CallbackType, subscription_messages: list[str]
110
+ ) -> Websocket:
111
+ """Шорткат для создания фьючерсного вебсокета."""
112
+ return Websocket(
113
+ callback=callback,
114
+ url=self._FUTURES_URL,
115
+ subscription_messages=subscription_messages,
116
+ ping_message='{"method": "ping"}',
117
+ **self._ws_kwargs,
118
+ )
119
+
120
+ def trade(
121
+ self,
122
+ callback: CallbackType,
123
+ symbol: str | None = None,
124
+ symbols: Sequence[str] | None = None,
125
+ update_interval: Literal["100ms", "10ms"] = "100ms",
126
+ ) -> Websocket:
127
+ """Создает вебсокет для получения сделок.
128
+
129
+ https://mexcdevelop.github.io/apidocs/spot_v3_en/#trade-streams
130
+
131
+ Параметры:
132
+ callback (`CallbackType`): Асинхронная функция обратного вызова для обработки сообщений.
133
+ symbol (`str | None`): Один символ для подписки.
134
+ symbols (`Sequence[str] | None`): Список символов для мультиплекс‑подключения.
135
+ update_interval (`Literal["100ms", "10ms"]`): Интервал обновления.
136
+
137
+ Возвращает:
138
+ `Websocket`: Объект для управления вебсокет соединением.
139
+ """
140
+ subscription_messages = self._generate_subscription_message(
141
+ channel_template="spot@public.aggre.deals.v3.api.pb@{update_interval}@{symbol}",
142
+ symbol=symbol,
143
+ symbols=symbols,
144
+ update_interval=update_interval,
145
+ )
146
+ return self._create_websocket(callback, subscription_messages)
147
+
148
+ def klines(
149
+ self,
150
+ callback: CallbackType,
151
+ interval: str,
152
+ symbol: str | None = None,
153
+ symbols: Sequence[str] | None = None,
154
+ ) -> Websocket:
155
+ """Создает вебсокет для получения K-line (candlestick) данных.
156
+
157
+ https://mexcdevelop.github.io/apidocs/spot_v3_en/#k-line-streams
158
+
159
+ Параметры:
160
+ callback (`CallbackType`): Асинхронная функция обратного вызова для обработки сообщений.
161
+ symbol (`str | None`): Один символ для подписки.
162
+ symbols (`Sequence[str] | None`): Список символов для мультиплекс‑подключения.
163
+ interval (`Literal[...]`): Интервал K-line.
164
+
165
+ Возвращает:
166
+ `Websocket`: Объект для управления вебсокет соединением.
167
+ """
168
+ subscription_messages = self._generate_subscription_message(
169
+ channel_template="spot@public.kline.v3.api.pb@{symbol}@{interval}",
170
+ symbol=symbol,
171
+ symbols=symbols,
172
+ interval=interval,
173
+ )
174
+ return self._create_websocket(callback, subscription_messages)
175
+
176
+ def diff_depth(
177
+ self,
178
+ callback: CallbackType,
179
+ symbol: str | None = None,
180
+ symbols: Sequence[str] | None = None,
181
+ update_speed: Literal["100ms", "10ms"] = "100ms",
182
+ ) -> Websocket:
183
+ """Создает вебсокет для получения инкрементальных изменений в книге заявок.
184
+
185
+ https://mexcdevelop.github.io/apidocs/spot_v3_en/#diff-depth-stream
186
+
187
+ Параметры:
188
+ callback (`CallbackType`): Асинхронная функция обратного вызова для обработки сообщений.
189
+ symbol (`str | None`): Один символ для подписки.
190
+ symbols (`Sequence[str] | None`): Список символов для мультиплекс‑подключения.
191
+ update_speed (`Literal["100ms", "10ms"]`): Скорость обновления данных.
192
+
193
+ Возвращает:
194
+ `Websocket`: Объект для управления вебсокет соединением.
195
+ """
196
+ subscription_messages = self._generate_subscription_message(
197
+ channel_template="spot@public.aggre.depth.v3.api.pb@{update_speed}@{symbol}",
198
+ symbol=symbol,
199
+ symbols=symbols,
200
+ update_speed=update_speed,
201
+ )
202
+ return self._create_websocket(callback, subscription_messages)
203
+
204
+ def partial_depth(
205
+ self,
206
+ callback: CallbackType,
207
+ symbol: str | None = None,
208
+ symbols: Sequence[str] | None = None,
209
+ levels: Literal["5", "10", "20"] = "5",
210
+ ) -> Websocket:
211
+ """Создает вебсокет для получения ограниченной глубины книги заявок.
212
+
213
+ https://mexcdevelop.github.io/apidocs/spot_v3_en/#partial-book-depth-streams
214
+
215
+ Параметры:
216
+ callback (`CallbackType`): Асинхронная функция обратного вызова для обработки сообщений.
217
+ symbol (`str | None`): Один символ для подписки.
218
+ symbols (`Sequence[str] | None`): Список символов для мультиплекс‑подключения.
219
+ levels (`Literal["5", "10", "20"]`): Количество уровней глубины.
220
+
221
+ Возвращает:
222
+ `Websocket`: Объект для управления вебсокет соединением.
223
+ """
224
+ subscription_messages = self._generate_subscription_message(
225
+ channel_template="spot@public.limit.depth.v3.api.pb@{symbol}@{levels}",
226
+ symbol=symbol,
227
+ symbols=symbols,
228
+ levels=levels,
229
+ )
230
+ return self._create_websocket(callback, subscription_messages)
231
+
232
+ def book_ticker(
233
+ self,
234
+ callback: CallbackType,
235
+ symbol: str | None = None,
236
+ symbols: Sequence[str] | None = None,
237
+ update_speed: Literal["100ms", "10ms"] = "100ms",
238
+ ) -> Websocket:
239
+ """Создает вебсокет для получения лучших цен покупки и продажи в реальном времени.
240
+
241
+ https://mexcdevelop.github.io/apidocs/spot_v3_en/#individual-symbol-book-ticker-streams
242
+
243
+ Параметры:
244
+ callback (`CallbackType`): Асинхронная функция обратного вызова для обработки сообщений.
245
+ symbol (`str | None`): Один символ для подписки.
246
+ symbols (`Sequence[str] | None`): Список символов для мультиплекс‑подключения.
247
+ update_speed (`Literal["100ms", "10ms"]`): Скорость обновления данных.
248
+
249
+ Возвращает:
250
+ `Websocket`: Объект для управления вебсокет соединением.
251
+ """
252
+ subscription_messages = self._generate_subscription_message(
253
+ channel_template="spot@public.aggre.bookTicker.v3.api.pb@{update_speed}@{symbol}",
254
+ symbol=symbol,
255
+ symbols=symbols,
256
+ update_speed=update_speed,
257
+ )
258
+ return self._create_websocket(callback, subscription_messages)
259
+
260
+ def book_ticker_batch(
261
+ self,
262
+ callback: CallbackType,
263
+ symbol: str | None = None,
264
+ symbols: Sequence[str] | None = None,
265
+ ) -> Websocket:
266
+ """Создает вебсокет для получения лучших цен покупки и продажи (батч версия).
267
+
268
+ https://mexcdevelop.github.io/apidocs/spot_v3_en/#individual-symbol-book-ticker-streams-batch-aggregation
269
+
270
+ Параметры:
271
+ callback (`CallbackType`): Асинхронная функция обратного вызова для обработки сообщений.
272
+ symbol (`str | None`): Один символ для подписки.
273
+ symbols (`Sequence[str] | None`): Список символов для мультиплекс‑подключения.
274
+
275
+ Возвращает:
276
+ `Websocket`: Объект для управления вебсокет соединением.
277
+ """
278
+ subscription_messages = self._generate_subscription_message(
279
+ channel_template="spot@public.bookTicker.batch.v3.api.pb@{symbol}",
280
+ symbol=symbol,
281
+ symbols=symbols,
282
+ )
283
+ return self._create_websocket(callback, subscription_messages)
284
+
285
+ def futures_tickers(
286
+ self,
287
+ callback: CallbackType,
288
+ ) -> Websocket:
289
+ """Создает вебсокет для получения тикеров всех фьючерсных контрактов.
290
+
291
+ https://mexcdevelop.github.io/apidocs/contract_v1_en/#public-channels
292
+
293
+ Параметры:
294
+ callback (`CallbackType`): Асинхронная функция обратного вызова для обработки сообщений.
295
+
296
+ Возвращает:
297
+ `Websocket`: Объект для управления вебсокет соединением.
298
+ """
299
+ subscription_messages = self._generate_futures_subscription_message(
300
+ topic="sub.tickers", require_symbol=False
301
+ )
302
+ return self._create_futures_websocket(callback, subscription_messages)
303
+
304
+ def futures_ticker(
305
+ self,
306
+ callback: CallbackType,
307
+ symbol: str | None = None,
308
+ symbols: Sequence[str] | None = None,
309
+ ) -> Websocket:
310
+ """Создает вебсокет для получения тикера конкретных фьючерсных контрактов.
311
+
312
+ https://mexcdevelop.github.io/apidocs/contract_v1_en/#public-channels
313
+
314
+ Параметры:
315
+ callback (`CallbackType`): Асинхронная функция обратного вызова для обработки сообщений.
316
+ symbol (`str | None`): Символ фьючерсного контракта.
317
+ symbols (`Sequence[str] | None`): Последовательность символов фьючерсных контрактов.
318
+
319
+ Возвращает:
320
+ `Websocket`: Объект для управления вебсокет соединением.
321
+ """
322
+ subscription_messages = self._generate_futures_subscription_message(
323
+ topic="sub.ticker", symbol=symbol, symbols=symbols
324
+ )
325
+ return self._create_futures_websocket(callback, subscription_messages)
326
+
327
+ def futures_depth(
328
+ self,
329
+ callback: CallbackType,
330
+ limit: Literal[5, 10, 20] | None = None,
331
+ is_full: bool = False,
332
+ compress: bool = False,
333
+ symbol: str | None = None,
334
+ symbols: Sequence[str] | None = None,
335
+ ) -> Websocket:
336
+ """Создает вебсокет для получения глубины рынка фьючерсных контрактов.
337
+
338
+ https://mexcdevelop.github.io/apidocs/contract_v1_en/#public-channels
339
+
340
+ Параметры:
341
+ callback (`CallbackType`): Асинхронная функция обратного вызова для обработки сообщений.
342
+ limit (`Literal[5, 10, 20] | None`): Количество уровней в стакане заявок.
343
+ is_full (`bool`): Получать полную глубину рынка.
344
+ compress (`bool`): Использовать сжатие данных.
345
+ symbol (`str | None`): Символ фьючерсного контракта.
346
+ symbols (`Sequence[str] | None`): Последовательность символов фьючерсных контрактов.
347
+
348
+ Возвращает:
349
+ `Websocket`: Объект для управления вебсокет соединением.
350
+ """
351
+ additional_params = {}
352
+ if limit:
353
+ additional_params["limit"] = limit
354
+ if compress:
355
+ additional_params["compress"] = compress
356
+ topic = "sub.depth"
357
+ if is_full:
358
+ topic += ".full"
359
+ subscription_messages = self._generate_futures_subscription_message(
360
+ topic=topic, symbol=symbol, symbols=symbols, **additional_params
361
+ )
362
+ return self._create_futures_websocket(callback, subscription_messages)
363
+
364
+ def futures_kline(
365
+ self,
366
+ callback: CallbackType,
367
+ interval: str,
368
+ symbol: str | None = None,
369
+ symbols: Sequence[str] | None = None,
370
+ ) -> Websocket:
371
+ """Создает вебсокет для получения свечных данных фьючерсных контрактов.
372
+
373
+ https://mexcdevelop.github.io/apidocs/contract_v1_en/#public-channels
374
+
375
+ Параметры:
376
+ callback (`CallbackType`): Асинхронная функция обратного вызова для обработки сообщений.
377
+ interval (`str`): Временной интервал для свечей.
378
+ symbol (`str | None`): Символ фьючерсного контракта.
379
+ symbols (`Sequence[str] | None`): Последовательность символов фьючерсных контрактов.
380
+
381
+ Возвращает:
382
+ `Websocket`: Объект для управления вебсокет соединением.
383
+ """
384
+ subscription_messages = self._generate_futures_subscription_message(
385
+ topic="sub.deal", symbol=symbol, symbols=symbols, interval=interval
386
+ )
387
+ return self._create_futures_websocket(callback, subscription_messages)
388
+
389
+ def funding_rate(
390
+ self,
391
+ callback: CallbackType,
392
+ symbol: str | None = None,
393
+ symbols: Sequence[str] | None = None,
394
+ ) -> Websocket:
395
+ """Создает вебсокет для получения ставки финансирования фьючерсных контрактов.
396
+
397
+ https://mexcdevelop.github.io/apidocs/contract_v1_en/#public-channels
398
+
399
+ Параметры:
400
+ callback (`CallbackType`): Асинхронная функция обратного вызова для обработки сообщений.
401
+ symbol (`str | None`): Символ фьючерсного контракта.
402
+ symbols (`Sequence[str] | None`): Последовательность символов фьючерсных контрактов.
403
+
404
+ Возвращает:
405
+ `Websocket`: Объект для управления вебсокет соединением.
406
+ """
407
+ subscription_messages = self._generate_futures_subscription_message(
408
+ topic="sub.funding.rate", symbol=symbol, symbols=symbols
409
+ )
410
+ return self._create_futures_websocket(callback, subscription_messages)
411
+
412
+ def futures_index_price(
413
+ self,
414
+ callback: CallbackType,
415
+ symbol: str | None = None,
416
+ symbols: Sequence[str] | None = None,
417
+ ) -> Websocket:
418
+ """Создает вебсокет для получения индексной цены фьючерсных контрактов.
419
+
420
+ https://mexcdevelop.github.io/apidocs/contract_v1_en/#public-channels
421
+
422
+ Параметры:
423
+ callback (`CallbackType`): Асинхронная функция обратного вызова для обработки сообщений.
424
+ symbol (`str | None`): Символ фьючерсного контракта.
425
+ symbols (`Sequence[str] | None`): Последовательность символов фьючерсных контрактов.
426
+
427
+ Возвращает:
428
+ `Websocket`: Объект для управления вебсокет соединением.
429
+ """
430
+ subscription_messages = self._generate_futures_subscription_message(
431
+ topic="sub.index.price", symbol=symbol, symbols=symbols
432
+ )
433
+ return self._create_futures_websocket(callback, subscription_messages)
434
+
435
+ def futures_fair_price(
436
+ self,
437
+ callback: CallbackType,
438
+ symbol: str | None = None,
439
+ symbols: Sequence[str] | None = None,
440
+ ) -> Websocket:
441
+ """Создает вебсокет для получения справедливой цены фьючерсных контрактов.
442
+
443
+ https://mexcdevelop.github.io/apidocs/contract_v1_en/#public-channels
444
+
445
+ Параметры:
446
+ callback (`CallbackType`): Асинхронная функция обратного вызова для обработки сообщений.
447
+ symbol (`str | None`): Символ фьючерсного контракта.
448
+ symbols (`Sequence[str] | None`): Последовательность символов фьючерсных контрактов.
449
+
450
+ Возвращает:
451
+ `Websocket`: Объект для управления вебсокет соединением.
452
+ """
453
+ subscription_messages = self._generate_futures_subscription_message(
454
+ topic="sub.fair.price", symbol=symbol, symbols=symbols
455
+ )
456
+ return self._create_futures_websocket(callback, subscription_messages)