unicex 0.1.16__tar.gz → 0.2.0__tar.gz

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 (76) hide show
  1. unicex-0.2.0/PKG-INFO +122 -0
  2. unicex-0.2.0/README.md +76 -0
  3. {unicex-0.1.16 → unicex-0.2.0}/pyproject.toml +4 -3
  4. {unicex-0.1.16 → unicex-0.2.0}/unicex/__init__.py +18 -8
  5. {unicex-0.1.16 → unicex-0.2.0}/unicex/_abc/__init__.py +2 -1
  6. {unicex-0.1.16 → unicex-0.2.0}/unicex/_abc/adapter.py +2 -0
  7. {unicex-0.1.16/unicex/_abc/asyncio → unicex-0.2.0/unicex/_abc}/uni_client.py +2 -2
  8. {unicex-0.1.16/unicex/_abc/asyncio → unicex-0.2.0/unicex/_abc}/uni_websocket_manager.py +1 -1
  9. {unicex-0.1.16/unicex/_base/asyncio → unicex-0.2.0/unicex/_base}/websocket.py +6 -1
  10. {unicex-0.1.16/unicex/binance/asyncio → unicex-0.2.0/unicex/binance}/__init__.py +1 -1
  11. {unicex-0.1.16 → unicex-0.2.0}/unicex/binance/adapter.py +82 -113
  12. {unicex-0.1.16/unicex/binance/asyncio → unicex-0.2.0/unicex/binance}/client.py +118 -72
  13. {unicex-0.1.16/unicex/binance/asyncio → unicex-0.2.0/unicex/binance}/uni_client.py +2 -2
  14. {unicex-0.1.16/unicex/binance/asyncio → unicex-0.2.0/unicex/binance}/uni_websocket_manager.py +3 -3
  15. {unicex-0.1.16/unicex/binance/asyncio → unicex-0.2.0/unicex/binance}/user_websocket.py +23 -7
  16. {unicex-0.1.16/unicex/binance/asyncio → unicex-0.2.0/unicex/binance}/websocket_manager.py +238 -53
  17. {unicex-0.1.16/unicex/bitget/asyncio → unicex-0.2.0/unicex/bitget}/__init__.py +4 -1
  18. {unicex-0.1.16 → unicex-0.2.0}/unicex/bitget/adapter.py +42 -41
  19. {unicex-0.1.16/unicex/bitget/asyncio → unicex-0.2.0/unicex/bitget}/client.py +168 -44
  20. {unicex-0.1.16/unicex/bitget/asyncio → unicex-0.2.0/unicex/bitget}/uni_client.py +2 -2
  21. {unicex-0.1.16/unicex/bitget/asyncio → unicex-0.2.0/unicex/bitget}/uni_websocket_manager.py +3 -3
  22. {unicex-0.1.16/unicex/bitget/asyncio → unicex-0.2.0/unicex/bitget}/websocket_manager.py +44 -4
  23. unicex-0.2.0/unicex/mapper.py +57 -0
  24. {unicex-0.1.16 → unicex-0.2.0}/unicex/types.py +5 -0
  25. {unicex-0.1.16 → unicex-0.2.0}/unicex/utils.py +43 -1
  26. unicex-0.2.0/unicex.egg-info/PKG-INFO +122 -0
  27. unicex-0.2.0/unicex.egg-info/SOURCES.txt +35 -0
  28. {unicex-0.1.16 → unicex-0.2.0}/unicex.egg-info/requires.txt +0 -2
  29. unicex-0.1.16/PKG-INFO +0 -110
  30. unicex-0.1.16/README.md +0 -63
  31. unicex-0.1.16/unicex/_abc/asyncio/__init__.py +0 -4
  32. unicex-0.1.16/unicex/_abc/sync/__init__.py +0 -4
  33. unicex-0.1.16/unicex/_abc/sync/uni_client.py +0 -275
  34. unicex-0.1.16/unicex/_abc/sync/uni_websocket_manager.py +0 -294
  35. unicex-0.1.16/unicex/_base/__init__.py +0 -6
  36. unicex-0.1.16/unicex/_base/sync/__init__.py +0 -7
  37. unicex-0.1.16/unicex/_base/sync/client.py +0 -186
  38. unicex-0.1.16/unicex/_base/sync/websocket.py +0 -239
  39. unicex-0.1.16/unicex/binance/__init__.py +0 -13
  40. unicex-0.1.16/unicex/binance/_mixins/__init__.py +0 -7
  41. unicex-0.1.16/unicex/binance/_mixins/client.py +0 -78
  42. unicex-0.1.16/unicex/binance/_mixins/user_websocket.py +0 -28
  43. unicex-0.1.16/unicex/binance/_mixins/websocket_manager.py +0 -45
  44. unicex-0.1.16/unicex/binance/sync/__init__.py +0 -9
  45. unicex-0.1.16/unicex/binance/sync/client.py +0 -1558
  46. unicex-0.1.16/unicex/binance/sync/uni_client.py +0 -176
  47. unicex-0.1.16/unicex/binance/sync/uni_websocket_manager.py +0 -166
  48. unicex-0.1.16/unicex/binance/sync/user_websocket.py +0 -166
  49. unicex-0.1.16/unicex/binance/sync/websocket_manager.py +0 -726
  50. unicex-0.1.16/unicex/binance/types.py +0 -365
  51. unicex-0.1.16/unicex/bitget/__init__.py +0 -1
  52. unicex-0.1.16/unicex/bitget/_mixins/__init__.py +0 -7
  53. unicex-0.1.16/unicex/bitget/_mixins/client.py +0 -125
  54. unicex-0.1.16/unicex/bitget/_mixins/user_websocket.py +0 -0
  55. unicex-0.1.16/unicex/bitget/_mixins/websocket_manager.py +0 -47
  56. unicex-0.1.16/unicex/bitget/sync/__init__.py +0 -0
  57. unicex-0.1.16/unicex/bitget/types.py +0 -72
  58. unicex-0.1.16/unicex/bybit/__init__.py +0 -9
  59. unicex-0.1.16/unicex/bybit/adapter.py +0 -170
  60. unicex-0.1.16/unicex/bybit/client.py +0 -1164
  61. unicex-0.1.16/unicex/bybit/types.py +0 -266
  62. unicex-0.1.16/unicex/bybit/uni_client.py +0 -166
  63. unicex-0.1.16/unicex/bybit/websocket.py +0 -7
  64. unicex-0.1.16/unicex/bybit/websocket_manager.py +0 -27
  65. unicex-0.1.16/unicex/mapper.py +0 -110
  66. unicex-0.1.16/unicex.egg-info/PKG-INFO +0 -110
  67. unicex-0.1.16/unicex.egg-info/SOURCES.txt +0 -69
  68. {unicex-0.1.16 → unicex-0.2.0}/LICENSE +0 -0
  69. {unicex-0.1.16 → unicex-0.2.0}/setup.cfg +0 -0
  70. {unicex-0.1.16/unicex/_base/asyncio → unicex-0.2.0/unicex/_base}/__init__.py +0 -0
  71. {unicex-0.1.16/unicex/_base/asyncio → unicex-0.2.0/unicex/_base}/client.py +0 -0
  72. {unicex-0.1.16 → unicex-0.2.0}/unicex/enums.py +0 -0
  73. {unicex-0.1.16 → unicex-0.2.0}/unicex/exceptions.py +0 -0
  74. {unicex-0.1.16 → unicex-0.2.0}/unicex/extra.py +0 -0
  75. {unicex-0.1.16 → unicex-0.2.0}/unicex.egg-info/dependency_links.txt +0 -0
  76. {unicex-0.1.16 → unicex-0.2.0}/unicex.egg-info/top_level.txt +0 -0
unicex-0.2.0/PKG-INFO ADDED
@@ -0,0 +1,122 @@
1
+ Metadata-Version: 2.4
2
+ Name: unicex
3
+ Version: 0.2.0
4
+ Summary: Unified Crypto Exchange API
5
+ Author-email: LoveBloodAndDiamonds <ayazshakirzyanov27@gmail.com>
6
+ License: BSD 3-Clause License
7
+
8
+ Copyright (c) 2025, LoveBloodAndDiamonds
9
+
10
+ Redistribution and use in source and binary forms, with or without
11
+ modification, are permitted provided that the following conditions are met:
12
+
13
+ 1. Redistributions of source code must retain the above copyright notice, this
14
+ list of conditions and the following disclaimer.
15
+
16
+ 2. Redistributions in binary form must reproduce the above copyright notice,
17
+ this list of conditions and the following disclaimer in the documentation
18
+ and/or other materials provided with the distribution.
19
+
20
+ 3. Neither the name of the copyright holder nor the names of its
21
+ contributors may be used to endorse or promote products derived from
22
+ this software without specific prior written permission.
23
+
24
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
28
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
+
35
+ Project-URL: Github, https://github.com/LoveBloodAndDiamonds/uni-cex-api
36
+ Project-URL: Author, https://t.me/LoveBloodAndDiamonds
37
+ Project-URL: Readthedocs, https://unicex.readthedocs.io/ru/latest/
38
+ Requires-Python: >=3.12
39
+ Description-Content-Type: text/markdown
40
+ License-File: LICENSE
41
+ Requires-Dist: aiohttp>=3.12.15
42
+ Requires-Dist: loguru>=0.7.3
43
+ Requires-Dist: orjson>=3.11.3
44
+ Requires-Dist: websockets>=15.0.1
45
+ Dynamic: license-file
46
+
47
+ # Unified Crypto Exchange API
48
+
49
+ `unicex` — асинхронная библиотека для работы с криптовалютными биржами, реализующая унифицированный интерфейс поверх «сырых» REST и WebSocket API разных бирж.
50
+
51
+ ## ✅ Статус реализации
52
+
53
+ | Exchange | Client | UniClient | Adapter | WebsocketManager | UniWebsocketManager | UserWebsocket |
54
+ |----------|--------|-----------|---------|------------------|---------------------|---------------|
55
+ | Binance | [x] | [x] | [x] | [x] | [x] | [x] |
56
+ | Bybit | [ ] | [ ] | [ ] | [ ] | [ ] | [ ] |
57
+ | Bitget | [ ] | [ ] | [ ] | [ ] | [ ] | [ ] |
58
+ | Okx | [ ] | [ ] | [ ] | [ ] | [ ] | [ ] |
59
+ | Mexc | [ ] | [ ] | [ ] | [ ] | [ ] | [ ] |
60
+ | Gate | [ ] | [ ] | [ ] | [ ] | [ ] | [ ] |
61
+
62
+ ---
63
+
64
+ ## 🚀 Быстрый старт
65
+
66
+ - Установка: `pip install unicex` или из исходников: `pip install -e .`
67
+ - Библиотека полностью асинхронная. Примеры импорта:
68
+ - Сырые клиенты: `from unicex.binance import Client`
69
+ - Унифицированные клиенты: `from unicex.binance import UniClient`
70
+ - Менеджеры WS: `from unicex.binance import WebsocketManager, UniWebsocketManager`
71
+
72
+ Пример: получить последние цены через унифицированный клиент Binance
73
+
74
+ ```
75
+ import asyncio
76
+ from unicex.binance import UniClient
77
+
78
+
79
+ async def main():
80
+ client = await UniClient.create()
81
+ prices = await client.last_price()
82
+ print(prices["BTCUSDT"])
83
+ await client.close()
84
+
85
+
86
+ if __name__ == "__main__":
87
+ asyncio.run(main())
88
+ ```
89
+
90
+ Пример: подписаться на трейды через унифицированный WS‑менеджер Bitget
91
+
92
+ ```
93
+ import asyncio
94
+ from unicex.bitget import UniWebsocketManager
95
+ from unicex import TradeDict
96
+
97
+
98
+ async def on_trade(msg: TradeDict):
99
+ print(msg)
100
+
101
+
102
+ async def main():
103
+ uwm = UniWebsocketManager()
104
+ socket = uwm.trades(callback=on_trade, symbol="BTCUSDT")
105
+ await socket.start()
106
+
107
+
108
+ if __name__ == "__main__":
109
+ asyncio.run(main())
110
+ ```
111
+
112
+ ---
113
+
114
+ ## 🧑‍💻 Блок для разработчика
115
+
116
+ ### 📋 Todo
117
+ - Добавить веса и рейт‑лимиты в документацию клиентов
118
+ - Пересмотреть вопрос: должен ли быть адаптер интерфейсом?
119
+ - Доделать BitgetClient и проверить типы
120
+ - Добавить overload к методам с `None, None`
121
+ - Определить порядок полей, возвращаемых адаптером
122
+ - Написать 1–2 примера
unicex-0.2.0/README.md ADDED
@@ -0,0 +1,76 @@
1
+ # Unified Crypto Exchange API
2
+
3
+ `unicex` — асинхронная библиотека для работы с криптовалютными биржами, реализующая унифицированный интерфейс поверх «сырых» REST и WebSocket API разных бирж.
4
+
5
+ ## ✅ Статус реализации
6
+
7
+ | Exchange | Client | UniClient | Adapter | WebsocketManager | UniWebsocketManager | UserWebsocket |
8
+ |----------|--------|-----------|---------|------------------|---------------------|---------------|
9
+ | Binance | [x] | [x] | [x] | [x] | [x] | [x] |
10
+ | Bybit | [ ] | [ ] | [ ] | [ ] | [ ] | [ ] |
11
+ | Bitget | [ ] | [ ] | [ ] | [ ] | [ ] | [ ] |
12
+ | Okx | [ ] | [ ] | [ ] | [ ] | [ ] | [ ] |
13
+ | Mexc | [ ] | [ ] | [ ] | [ ] | [ ] | [ ] |
14
+ | Gate | [ ] | [ ] | [ ] | [ ] | [ ] | [ ] |
15
+
16
+ ---
17
+
18
+ ## 🚀 Быстрый старт
19
+
20
+ - Установка: `pip install unicex` или из исходников: `pip install -e .`
21
+ - Библиотека полностью асинхронная. Примеры импорта:
22
+ - Сырые клиенты: `from unicex.binance import Client`
23
+ - Унифицированные клиенты: `from unicex.binance import UniClient`
24
+ - Менеджеры WS: `from unicex.binance import WebsocketManager, UniWebsocketManager`
25
+
26
+ Пример: получить последние цены через унифицированный клиент Binance
27
+
28
+ ```
29
+ import asyncio
30
+ from unicex.binance import UniClient
31
+
32
+
33
+ async def main():
34
+ client = await UniClient.create()
35
+ prices = await client.last_price()
36
+ print(prices["BTCUSDT"])
37
+ await client.close()
38
+
39
+
40
+ if __name__ == "__main__":
41
+ asyncio.run(main())
42
+ ```
43
+
44
+ Пример: подписаться на трейды через унифицированный WS‑менеджер Bitget
45
+
46
+ ```
47
+ import asyncio
48
+ from unicex.bitget import UniWebsocketManager
49
+ from unicex import TradeDict
50
+
51
+
52
+ async def on_trade(msg: TradeDict):
53
+ print(msg)
54
+
55
+
56
+ async def main():
57
+ uwm = UniWebsocketManager()
58
+ socket = uwm.trades(callback=on_trade, symbol="BTCUSDT")
59
+ await socket.start()
60
+
61
+
62
+ if __name__ == "__main__":
63
+ asyncio.run(main())
64
+ ```
65
+
66
+ ---
67
+
68
+ ## 🧑‍💻 Блок для разработчика
69
+
70
+ ### 📋 Todo
71
+ - Добавить веса и рейт‑лимиты в документацию клиентов
72
+ - Пересмотреть вопрос: должен ли быть адаптер интерфейсом?
73
+ - Доделать BitgetClient и проверить типы
74
+ - Добавить overload к методам с `None, None`
75
+ - Определить порядок полей, возвращаемых адаптером
76
+ - Написать 1–2 примера
@@ -4,7 +4,7 @@ name = "unicex"
4
4
  # • PATCH (x.y.Z) → увеличивается при багфиксе, который не ломает совместимость.
5
5
  # • MINOR (x.Y.z) → увеличивается при добавлении новой функциональности, но без ломающих изменений (backward-compatible).
6
6
  # • MAJOR (X.y.z) → увеличивается при изменениях, которые ломают обратную совместимость.
7
- version = "0.1.16"
7
+ version = "0.2.0"
8
8
 
9
9
  description = "Unified Crypto Exchange API "
10
10
  readme = "README.md"
@@ -17,18 +17,19 @@ dependencies = [
17
17
  "aiohttp>=3.12.15",
18
18
  "loguru>=0.7.3",
19
19
  "orjson>=3.11.3",
20
- "requests>=2.32.5",
21
- "websocket-client>=1.8.0",
22
20
  "websockets>=15.0.1",
23
21
  ]
24
22
 
25
23
  [project.urls]
26
24
  Github = "https://github.com/LoveBloodAndDiamonds/uni-cex-api"
27
25
  Author = "https://t.me/LoveBloodAndDiamonds"
26
+ Readthedocs = "https://unicex.readthedocs.io/ru/latest/"
28
27
 
29
28
  [dependency-groups]
30
29
  dev = [
31
30
  "build>=1.3.0",
32
31
  "pre-commit>=4.3.0",
32
+ "sphinx>=8.2.3",
33
+ "sphinx-rtd-theme>=3.0.2",
33
34
  "twine>=6.2.0",
34
35
  ]
@@ -20,21 +20,31 @@ __all__ = [
20
20
  "IUniClient",
21
21
  "IUniWebsocketManager",
22
22
  "IAdapter",
23
- "IUniAsyncClient",
24
- "IUniAsyncWebsocketManager",
25
23
  # Base clients and websockets
26
24
  "Websocket",
27
25
  "BaseClient",
28
- "AsyncWebsocket",
29
- "BaseAsyncClient",
26
+ # Binance
27
+ "BinanceClient",
28
+ "BinanceUniClient",
29
+ "BinanceWebsocketManager",
30
+ "BinanceUniWebsocketManager",
31
+ # Bitget
32
+ "BitgetClient",
33
+ "BitgetUniClient",
34
+ "BitgetUniWebsocketManager",
35
+ "BitgetWebsocketManager",
30
36
  ]
31
37
 
32
38
  from ._abc import IAdapter, IUniClient, IUniWebsocketManager
33
- from ._abc.asyncio import IUniClient as IUniAsyncClient
34
- from ._abc.asyncio import IUniWebsocketManager as IUniAsyncWebsocketManager
35
39
  from ._base import BaseClient, Websocket
36
- from ._base.asyncio import BaseClient as BaseAsyncClient
37
- from ._base.asyncio import Websocket as AsyncWebsocket
40
+ from .binance import Client as BinanceClient
41
+ from .binance import UniClient as BinanceUniClient
42
+ from .binance import UniWebsocketManager as BinanceUniWebsocketManager
43
+ from .binance import WebsocketManager as BinanceWebsocketManager
44
+ from .bitget import Client as BitgetClient
45
+ from .bitget import UniClient as BitgetUniClient
46
+ from .bitget import UniWebsocketManager as BitgetUniWebsocketManager
47
+ from .bitget import WebsocketManager as BitgetWebsocketManager
38
48
  from .enums import Exchange, MarketType, Side, Timeframe
39
49
  from .mapper import get_uni_client, get_uni_websocket_manager
40
50
  from .types import AggTradeDict, KlineDict, LoggerLike, RequestMethod, TickerDailyDict, TradeDict
@@ -5,4 +5,5 @@ __all__ = [
5
5
  ]
6
6
 
7
7
  from .adapter import IAdapter
8
- from .sync import IUniClient, IUniWebsocketManager
8
+ from .uni_client import IUniClient
9
+ from .uni_websocket_manager import IUniWebsocketManager
@@ -1,3 +1,5 @@
1
+ __all__ = ["IAdapter"]
2
+
1
3
  from abc import ABC, abstractmethod
2
4
  from typing import Any
3
5
 
@@ -6,12 +6,12 @@ from typing import Generic, Self, TypeVar, overload
6
6
 
7
7
  import aiohttp
8
8
 
9
- from unicex._base.asyncio import BaseClient
9
+ from unicex._base import BaseClient
10
10
  from unicex.enums import Timeframe
11
11
  from unicex.types import KlineDict, LoggerLike, TickerDailyDict
12
12
  from unicex.utils import batched_list
13
13
 
14
- from ..adapter import IAdapter
14
+ from .adapter import IAdapter
15
15
 
16
16
  TClient = TypeVar("TClient", bound="BaseClient")
17
17
 
@@ -6,7 +6,7 @@ from typing import Any, overload
6
6
 
7
7
  from loguru import logger as _logger
8
8
 
9
- from unicex._base.asyncio import BaseClient, Websocket
9
+ from unicex._base import BaseClient, Websocket
10
10
  from unicex.enums import Timeframe
11
11
  from unicex.types import LoggerLike
12
12
 
@@ -183,7 +183,12 @@ class Websocket:
183
183
  break
184
184
  except Exception as e:
185
185
  self._logger.error(f"{self} Error({type(e)}) while processing message: {e}")
186
- self._queue.task_done()
186
+
187
+ try:
188
+ self._queue.task_done()
189
+ except Exception as e:
190
+ if self._running:
191
+ self._logger.error(f"{self} Error({type(e)}) while marking task done: {e}")
187
192
 
188
193
  def _generate_ws_kwargs(self) -> dict:
189
194
  """Генерирует аргументы для запуска вебсокета."""
@@ -1,4 +1,4 @@
1
- """Пакет содержит асинхронные клиенты и менеджеры для работы с биржей Binance."""
1
+ """Пакет, содержащий реализации клиентов и менеджеров для работы с биржей Binance."""
2
2
 
3
3
  __all__ = ["Client", "UniClient", "UserWebsocket", "WebsocketManager", "UniWebsocketManager"]
4
4
 
@@ -2,14 +2,15 @@ __all__ = ["Adapter"]
2
2
 
3
3
 
4
4
  from unicex._abc import IAdapter
5
- from unicex.exceptions import AdapterError
6
5
  from unicex.types import AggTradeDict, KlineDict, TickerDailyDict, TradeDict
6
+ from unicex.utils import catch_adapter_errors
7
7
 
8
8
 
9
9
  class Adapter(IAdapter):
10
10
  """Адаптер для унификации данных с Binance API."""
11
11
 
12
12
  @staticmethod
13
+ @catch_adapter_errors
13
14
  def tickers(raw_data: list[dict], only_usdt: bool = True) -> list[str]:
14
15
  """Преобразует сырой ответ, в котором содержатся данные о тикерах в список тикеров.
15
16
 
@@ -20,18 +21,12 @@ class Adapter(IAdapter):
20
21
  Возвращает:
21
22
  list[str]: Список тикеров.
22
23
  """
23
- try:
24
- return [
25
- item["symbol"]
26
- for item in raw_data
27
- if not only_usdt or item["symbol"].endswith("USDT")
28
- ]
29
- except Exception as e:
30
- raise AdapterError(
31
- f"({type(e)}): {e}. Can not convert {raw_data} to unified tickers."
32
- ) from e
24
+ return [
25
+ item["symbol"] for item in raw_data if not only_usdt or item["symbol"].endswith("USDT")
26
+ ]
33
27
 
34
28
  @staticmethod
29
+ @catch_adapter_errors
35
30
  def futures_tickers(raw_data: list[dict], only_usdt: bool = True) -> list[str]:
36
31
  """Преобразует сырой ответ, в котором содержатся данные о тикерах в список тикеров.
37
32
 
@@ -45,6 +40,7 @@ class Adapter(IAdapter):
45
40
  return Adapter.tickers(raw_data, only_usdt)
46
41
 
47
42
  @staticmethod
43
+ @catch_adapter_errors
48
44
  def ticker_24h(raw_data: list[dict]) -> dict[str, TickerDailyDict]:
49
45
  """Преобразует сырой ответ, в котором содержатся данные о тикере за последние 24 часа в унифицированный формат.
50
46
 
@@ -54,21 +50,17 @@ class Adapter(IAdapter):
54
50
  Возвращает:
55
51
  dict[str, TickerDailyDict]: Словарь, где ключ - тикер, а значение - статистика за последние 24 часа.
56
52
  """
57
- try:
58
- return {
59
- item["symbol"]: TickerDailyDict(
60
- p=float(item["priceChangePercent"]),
61
- q=float(item["quoteVolume"]), # объём в долларах
62
- v=float(item["volume"]), # объём в монетах
63
- )
64
- for item in raw_data
65
- }
66
- except Exception as e:
67
- raise AdapterError(
68
- f"({type(e)}): {e}. Can not convert {raw_data} to unified ticker 24h."
69
- ) from e
53
+ return {
54
+ item["symbol"]: TickerDailyDict(
55
+ p=float(item["priceChangePercent"]),
56
+ q=float(item["quoteVolume"]), # объём в долларах
57
+ v=float(item["volume"]), # объём в монетах
58
+ )
59
+ for item in raw_data
60
+ }
70
61
 
71
62
  @staticmethod
63
+ @catch_adapter_errors
72
64
  def futures_ticker_24h(raw_data: list[dict]) -> dict[str, TickerDailyDict]:
73
65
  """Преобразует сырой ответ, в котором содержатся данные о тикере за последние 24 часа в унифицированный формат.
74
66
 
@@ -81,6 +73,7 @@ class Adapter(IAdapter):
81
73
  return Adapter.ticker_24h(raw_data)
82
74
 
83
75
  @staticmethod
76
+ @catch_adapter_errors
84
77
  def last_price(raw_data: list[dict]) -> dict[str, float]:
85
78
  """Преобразует сырой ответ, в котором содержатся данные о тикере за последние 24 часа в унифицированный формат.
86
79
 
@@ -90,14 +83,10 @@ class Adapter(IAdapter):
90
83
  Возвращает:
91
84
  dict[str, float]: Словарь, где ключ - тикер, а значение - последняя цена.
92
85
  """
93
- try:
94
- return {item["symbol"]: float(item["price"]) for item in raw_data}
95
- except Exception as e:
96
- raise AdapterError(
97
- f"({type(e)}): {e}. Can not convert {raw_data} to unified last price."
98
- ) from e
86
+ return {item["symbol"]: float(item["price"]) for item in raw_data}
99
87
 
100
88
  @staticmethod
89
+ @catch_adapter_errors
101
90
  def futures_last_price(raw_data: list[dict]) -> dict[str, float]:
102
91
  """Преобразует сырой ответ, в котором содержатся данные о тикере за последние 24 часа в унифицированный формат.
103
92
 
@@ -110,6 +99,7 @@ class Adapter(IAdapter):
110
99
  return Adapter.last_price(raw_data)
111
100
 
112
101
  @staticmethod
102
+ @catch_adapter_errors
113
103
  def klines(raw_data: list[list]) -> list[KlineDict]:
114
104
  """Преобразует сырой ответ, в котором содержатся данные о котировках тикеров в унифицированный формат.
115
105
 
@@ -119,28 +109,24 @@ class Adapter(IAdapter):
119
109
  Возвращает:
120
110
  list[KlineDict]: Список словарей, где каждый словарь содержит данные о свече.
121
111
  """
122
- try:
123
- return [
124
- KlineDict(
125
- s="",
126
- t=item[0],
127
- o=float(item[1]),
128
- h=float(item[2]),
129
- l=float(item[3]),
130
- c=float(item[4]),
131
- v=float(item[5]),
132
- q=float(item[7]),
133
- T=item[6],
134
- x=None,
135
- )
136
- for item in raw_data
137
- ]
138
- except Exception as e:
139
- raise AdapterError(
140
- f"({type(e)}): {e}. Can not convert {raw_data} to unified kline."
141
- ) from e
112
+ return [
113
+ KlineDict(
114
+ s="",
115
+ t=item[0],
116
+ o=float(item[1]),
117
+ h=float(item[2]),
118
+ l=float(item[3]),
119
+ c=float(item[4]),
120
+ v=float(item[5]),
121
+ q=float(item[7]),
122
+ T=item[6],
123
+ x=None,
124
+ )
125
+ for item in raw_data
126
+ ]
142
127
 
143
128
  @staticmethod
129
+ @catch_adapter_errors
144
130
  def futures_klines(raw_data: list[list]) -> list[KlineDict]:
145
131
  """Преобразует сырой ответ, в котором содержатся данные о котировках тикеров в унифицированный формат.
146
132
 
@@ -153,6 +139,7 @@ class Adapter(IAdapter):
153
139
  return Adapter.klines(raw_data)
154
140
 
155
141
  @staticmethod
142
+ @catch_adapter_errors
156
143
  def funding_rate(raw_data: list[dict]) -> dict[str, float]:
157
144
  """Преобразует сырой ответ, в котором содержатся данные о ставках финансирования тикеров в унифицированный формат.
158
145
 
@@ -162,14 +149,10 @@ class Adapter(IAdapter):
162
149
  Возвращает:
163
150
  dict[str, float]: Словарь, где ключ - тикер, а значение - ставка финансирования.
164
151
  """
165
- try:
166
- return {item["symbol"]: float(item["lastFundingRate"]) * 100 for item in raw_data}
167
- except Exception as e:
168
- raise AdapterError(
169
- f"({type(e)}): {e}. Can not convert {raw_data} to unified funding rate."
170
- ) from e
152
+ return {item["symbol"]: float(item["lastFundingRate"]) * 100 for item in raw_data}
171
153
 
172
154
  @staticmethod
155
+ @catch_adapter_errors
173
156
  def klines_message(raw_msg: dict) -> list[KlineDict]:
174
157
  """Преобразует сырое сообщение с вебсокета, в котором содержится информация о
175
158
  свече/свечах в унифицированный вид.
@@ -180,29 +163,25 @@ class Adapter(IAdapter):
180
163
  Возвращает:
181
164
  list[KlineDict]: Список словарей, где каждый словарь содержит данные о свече.
182
165
  """
183
- try:
184
- # Обрабатываем обертку в случае с multiplex stream
185
- kline = raw_msg.get("data", raw_msg)["k"]
186
- return [
187
- KlineDict(
188
- s=kline["s"],
189
- t=kline["t"],
190
- o=float(kline["o"]),
191
- h=float(kline["h"]),
192
- l=float(kline["l"]),
193
- c=float(kline["c"]),
194
- v=float(kline["v"]), # Используем quote volume (в USDT)
195
- q=float(kline["q"]), # Используем quote volume (в USDT)
196
- T=kline["T"],
197
- x=kline["x"],
198
- )
199
- ]
200
- except Exception as e:
201
- raise AdapterError(
202
- f"({type(e)}): {e}. Can not convert {raw_msg} to unified kline."
203
- ) from e
166
+ # Обрабатываем обертку в случае с multiplex stream
167
+ kline = raw_msg.get("data", raw_msg)["k"]
168
+ return [
169
+ KlineDict(
170
+ s=kline["s"],
171
+ t=kline["t"],
172
+ o=float(kline["o"]),
173
+ h=float(kline["h"]),
174
+ l=float(kline["l"]),
175
+ c=float(kline["c"]),
176
+ v=float(kline["v"]), # Используем quote volume (в USDT)
177
+ q=float(kline["q"]), # Используем quote volume (в USDT)
178
+ T=kline["T"],
179
+ x=kline["x"],
180
+ )
181
+ ]
204
182
 
205
183
  @staticmethod
184
+ @catch_adapter_errors
206
185
  def futures_klines_message(raw_msg: dict) -> list[KlineDict]:
207
186
  """Преобразует сырое сообщение с вебсокета, в котором содержится информация о
208
187
  свече/свечах в унифицированный вид.
@@ -216,6 +195,7 @@ class Adapter(IAdapter):
216
195
  return Adapter.klines_message(raw_msg)
217
196
 
218
197
  @staticmethod
198
+ @catch_adapter_errors
219
199
  def aggtrades_message(raw_msg: dict) -> list[AggTradeDict]:
220
200
  """Преобразует сырое сообщение с вебсокета, в котором содержится информация о
221
201
  аггрегированных сделке/сделках в унифицированный вид.
@@ -226,23 +206,19 @@ class Adapter(IAdapter):
226
206
  Возвращает:
227
207
  list[KlineDict]: Список словарей, где каждый словарь содержит данные о сделке.
228
208
  """
229
- try:
230
- msg = raw_msg.get("data", raw_msg)
231
- return [
232
- AggTradeDict(
233
- t=int(msg["T"]),
234
- s=str(msg["s"]),
235
- S="SELL" if bool(msg["m"]) else "BUY",
236
- p=float(msg["p"]),
237
- v=float(msg["q"]),
238
- )
239
- ]
240
- except Exception as e:
241
- raise AdapterError(
242
- f"({type(e)}): {e}. Can not convert {raw_msg} to unified aggtrade."
243
- ) from e
209
+ msg = raw_msg.get("data", raw_msg)
210
+ return [
211
+ AggTradeDict(
212
+ t=int(msg["T"]),
213
+ s=str(msg["s"]),
214
+ S="SELL" if bool(msg["m"]) else "BUY",
215
+ p=float(msg["p"]),
216
+ v=float(msg["q"]),
217
+ )
218
+ ]
244
219
 
245
220
  @staticmethod
221
+ @catch_adapter_errors
246
222
  def futures_aggtrades_message(raw_msg: dict) -> list[AggTradeDict]:
247
223
  """Преобразует сырое сообщение с вебсокета, в котором содержится информация о
248
224
  аггрегированных сделке/сделках в унифицированный вид.
@@ -256,6 +232,7 @@ class Adapter(IAdapter):
256
232
  return Adapter.aggtrades_message(raw_msg)
257
233
 
258
234
  @staticmethod
235
+ @catch_adapter_errors
259
236
  def trades_message(raw_msg: dict) -> list[TradeDict]:
260
237
  """Преобразует сырое сообщение с вебсокета, в котором содержится информация о
261
238
  сделке/сделках в унифицированный вид.
@@ -266,23 +243,19 @@ class Adapter(IAdapter):
266
243
  Возвращает:
267
244
  list[KlineDict]: Список словарей, где каждый словарь содержит данные о сделке.
268
245
  """
269
- try:
270
- msg = raw_msg.get("data", raw_msg)
271
- return [
272
- TradeDict(
273
- t=int(msg["T"]),
274
- s=str(msg["s"]),
275
- S="SELL" if bool(msg["m"]) else "BUY",
276
- p=float(msg["p"]),
277
- v=float(msg["q"]),
278
- )
279
- ]
280
- except Exception as e:
281
- raise AdapterError(
282
- f"({type(e)}): {e}. Can not convert {raw_msg} to unified trade."
283
- ) from e
246
+ msg = raw_msg.get("data", raw_msg)
247
+ return [
248
+ TradeDict(
249
+ t=int(msg["T"]),
250
+ s=str(msg["s"]),
251
+ S="SELL" if bool(msg["m"]) else "BUY",
252
+ p=float(msg["p"]),
253
+ v=float(msg["q"]),
254
+ )
255
+ ]
284
256
 
285
257
  @staticmethod
258
+ @catch_adapter_errors
286
259
  def futures_trades_message(raw_msg: dict) -> list[TradeDict]:
287
260
  """Преобразует сырое сообщение с вебсокета, в котором содержится информация о
288
261
  сделке/сделках в унифицированный вид.
@@ -296,6 +269,7 @@ class Adapter(IAdapter):
296
269
  return Adapter.trades_message(raw_msg)
297
270
 
298
271
  @staticmethod
272
+ @catch_adapter_errors
299
273
  def open_interest(raw_data: dict) -> float:
300
274
  """Преобразует сырое сообщение с вебсокета, в котором содержится информация о
301
275
  объеме открытых позиций в унифицированный вид.
@@ -306,9 +280,4 @@ class Adapter(IAdapter):
306
280
  Возвращает:
307
281
  float: Объем открытых позиций в монетах.
308
282
  """
309
- try:
310
- return float(raw_data["openInterest"])
311
- except Exception as e:
312
- raise AdapterError(
313
- f"{type(e)}: {e}. Can not convert {raw_data} to unified open interest."
314
- ) from e
283
+ return float(raw_data["openInterest"])