xync-client 0.0.25.dev3__tar.gz → 0.0.25.dev4__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 (75) hide show
  1. {xync_client-0.0.25.dev3/xync_client.egg-info → xync_client-0.0.25.dev4}/PKG-INFO +1 -1
  2. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/tests/TestEx.py +26 -11
  3. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Abc/BaseTest.py +14 -7
  4. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Abc/Ex.py +15 -8
  5. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/TgWallet/ex.py +4 -5
  6. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/TgWallet/pyd.py +2 -2
  7. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4/xync_client.egg-info}/PKG-INFO +1 -1
  8. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/.env.sample +0 -0
  9. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/.gitignore +0 -0
  10. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/.pre-commit-config.yaml +0 -0
  11. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/README.md +0 -0
  12. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/makefile +0 -0
  13. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/pyproject.toml +0 -0
  14. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/setup.cfg +0 -0
  15. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/tests/TestAgent.py +0 -0
  16. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/tests/TestAsset.py +0 -0
  17. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/tests/TestOrder.py +0 -0
  18. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/tests/_todo_refact/Binance/test_binance.py +0 -0
  19. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/tests/_todo_refact/Bybit/test_bybit.py +0 -0
  20. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/tests/_todo_refact/Bybit/test_bybit_p2p.py +0 -0
  21. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/tests/_todo_refact/Gate/test_gate.py +0 -0
  22. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/tests/_todo_refact/Htx/test_htx_p2p.py +0 -0
  23. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/tests/_todo_refact/Wallet/test_agent.py +0 -0
  24. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/tests/_todo_refact/Wallet/test_ex.py +0 -0
  25. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/tests/_todo_refact/__init__.py +0 -0
  26. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/tests/_todo_refact/_test_ex.py +0 -0
  27. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Abc/Agent.py +0 -0
  28. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Abc/Asset.py +0 -0
  29. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Abc/AuthTrait.py +0 -0
  30. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Abc/Base.py +0 -0
  31. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Abc/InAgent.py +0 -0
  32. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Abc/Order.py +0 -0
  33. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Binance/__init__.py +0 -0
  34. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Binance/binance_async.py +0 -0
  35. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Binance/earn_api.py +0 -0
  36. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Binance/ex.py +0 -0
  37. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Binance/exceptions.py +0 -0
  38. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Binance/sapi.py +0 -0
  39. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Binance/web_c2c.py +0 -0
  40. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/BingX/__init__.py +0 -0
  41. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/BingX/agent.py +0 -0
  42. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/BingX/base.py +0 -0
  43. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/BingX/ex.py +0 -0
  44. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/BingX/req.mjs +0 -0
  45. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/BingX/sign.js +0 -0
  46. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/BingX/test/main.py +0 -0
  47. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/BitGet/__init__.py +0 -0
  48. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/BitGet/agent.py +0 -0
  49. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/BitGet/ex.py +0 -0
  50. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/BitGet/req.mjs +0 -0
  51. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Bybit/agent.py +0 -0
  52. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Bybit/ex.py +0 -0
  53. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Bybit/web_earn.py +0 -0
  54. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Bybit/web_p2p.py +0 -0
  55. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Gate/ex.py +0 -0
  56. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Gate/premarket.py +0 -0
  57. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Htx/agent.py +0 -0
  58. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Htx/earn.py +0 -0
  59. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Htx/ex.py +0 -0
  60. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/KuCoin/pub.py +0 -0
  61. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/KuCoin/web.py +0 -0
  62. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/Okx/ex.py +0 -0
  63. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/TgWallet/agent.py +0 -0
  64. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/TgWallet/asset.py +0 -0
  65. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/TgWallet/auth.py +0 -0
  66. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/TgWallet/inAgent.py +0 -0
  67. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/TgWallet/order.py +0 -0
  68. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/TgWallet/pyro.py +0 -0
  69. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/TgWallet/web.py +0 -0
  70. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/__init__.py +0 -0
  71. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client/loader.py +0 -0
  72. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client.egg-info/SOURCES.txt +0 -0
  73. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client.egg-info/dependency_links.txt +0 -0
  74. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client.egg-info/requires.txt +0 -0
  75. {xync_client-0.0.25.dev3 → xync_client-0.0.25.dev4}/xync_client.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: xync-client
3
- Version: 0.0.25.dev3
3
+ Version: 0.0.25.dev4
4
4
  Author-email: Mike Artemiev <mixartemev@gmail.com>
5
5
  Project-URL: Homepage, https://gitlab.com/XyncNet/client
6
6
  Project-URL: Repository, https://gitlab.com/XyncNet/client
@@ -1,16 +1,20 @@
1
1
  import logging
2
2
 
3
3
  import pytest
4
+ from xync_schema.pydantic import PmPyd, BaseAd
5
+
4
6
  from xync_client.Abc.BaseTest import BaseTest
5
7
  from xync_schema.enums import ExStatus, ExType, ExAction
6
8
  from xync_schema.models import Ex, TestEx as ExTest
7
9
 
8
- from xync_client.Abc.Base import BaseClient, DictOfDicts, FlatDict, MapOfIdsList
10
+ from xync_client.Abc.Base import BaseClient, FlatDict, MapOfIdsList
9
11
  from xync_client.Abc.Ex import BaseExClient
10
12
 
11
13
 
12
14
  @pytest.mark.asyncio(loop_scope="session")
13
15
  class TestEx(BaseTest):
16
+ ad: dict[str, BaseAd] = {}
17
+
14
18
  @pytest.fixture
15
19
  async def clients(self) -> list[BaseClient]:
16
20
  exs = await Ex.filter(status__gt=ExStatus.plan)
@@ -26,15 +30,16 @@ class TestEx(BaseTest):
26
30
  ok = self.is_flat_dict(curs)
27
31
  t, _ = await ExTest.update_or_create({"ok": ok}, ex=client.ex, action=ExAction.curs)
28
32
  assert t.ok, "No curs"
29
- logging.info(f"{client.ex.name}:{ExAction.curs.name} - ok")
33
+ logging.info(f"{client.ex.name}: {ExAction.curs.name} - ok")
30
34
 
31
35
  # 20
32
36
  async def test_pms(self, clients: list[BaseExClient]):
33
37
  for client in clients:
34
- pms: DictOfDicts = await client.pms()
35
- t, _ = await ExTest.update_or_create({"ok": self.is_dict_of_dicts(pms)}, ex=client.ex, action=ExAction.pms)
38
+ pms: dict[int | str, PmPyd] = await client.pms()
39
+ ok = self.is_dict_of_objects(pms, PmPyd)
40
+ t, _ = await ExTest.update_or_create({"ok": ok}, ex=client.ex, action=ExAction.pms)
36
41
  assert t.ok, "No pms"
37
- logging.info(f"{client.ex.name}:{ExAction.pms.name} - ok")
42
+ logging.info(f"{client.ex.name}: {ExAction.pms.name} - ok")
38
43
 
39
44
  # 21
40
45
  async def test_cur_pms_map(self, clients: list[BaseExClient]):
@@ -43,7 +48,7 @@ class TestEx(BaseTest):
43
48
  ok = self.is_map_of_ids(cur_pms)
44
49
  t, _ = await ExTest.update_or_create({"ok": ok}, ex=client.ex, action=ExAction.cur_pms_map)
45
50
  assert t.ok, "No pms for cur"
46
- logging.info(f"{client.ex.name}:{ExAction.cur_pms_map.name} - ok")
51
+ logging.info(f"{client.ex.name}: {ExAction.cur_pms_map.name} - ok")
47
52
 
48
53
  # 22
49
54
  async def test_coins(self, clients: list[BaseExClient]):
@@ -52,7 +57,7 @@ class TestEx(BaseTest):
52
57
  ok = self.is_flat_dict(coins)
53
58
  t, _ = await ExTest.update_or_create({"ok": ok}, ex=client.ex, action=ExAction.coins)
54
59
  assert t.ok, "No coins"
55
- logging.info(f"{client.ex.name}:{ExAction.coins.name} - ok")
60
+ logging.info(f"{client.ex.name}: {ExAction.coins.name} - ok")
56
61
 
57
62
  # 23
58
63
  async def test_pairs(self, clients: list[BaseExClient]):
@@ -61,13 +66,23 @@ class TestEx(BaseTest):
61
66
  ok = self.is_map_of_ids(pairs)
62
67
  t, _ = await ExTest.update_or_create({"ok": ok}, ex=client.ex, action=ExAction.pairs)
63
68
  assert t.ok, "No coins"
64
- logging.info(f"{client.ex.name}:{ExAction.pairs.name} - ok")
69
+ logging.info(f"{client.ex.name}: {ExAction.pairs.name} - ok")
65
70
 
66
71
  # 24
67
72
  async def test_ads(self, clients: list[BaseExClient]):
68
73
  for client in clients:
69
- ads: FlatDict = await client.ads("USDT", "RUB", False)
70
- ok = self.is_list_of_dicts(ads)
74
+ ads: list[BaseAd] = await client.ads("USDT", "RUB", False)
75
+ ok = self.is_list_of_objects(ads, BaseAd)
71
76
  t, _ = await ExTest.update_or_create({"ok": ok}, ex=client.ex, action=ExAction.ads)
72
77
  assert t.ok, "No ads"
73
- logging.info(f"{client.ex.name}:{ExAction.ads.name} - ok")
78
+ self.ad[client.ex.name] = ads[0] # for further use in test_ad
79
+ logging.info(f"{client.ex.name}: {ExAction.ads.name} - ok")
80
+
81
+ # 42
82
+ async def test_ad(self, clients: list[BaseExClient]):
83
+ for client in clients:
84
+ ad: BaseAd = await client.ad(self.ad[client.ex.name].id)
85
+ ok = isinstance(ad, BaseAd)
86
+ t, _ = await ExTest.update_or_create({"ok": ok}, ex=client.ex, action=ExAction.ad)
87
+ assert t.ok, "No ad"
88
+ logging.info(f"{client.ex.name}: {ExAction.ad.name} - ok")
@@ -1,11 +1,8 @@
1
- from abc import abstractmethod
2
-
3
- # from asyncio import AbstractEventLoop
4
- from typing import TypeGuard
5
-
6
1
  import pytest
7
2
 
8
3
  # import uvloop
4
+ from abc import abstractmethod
5
+ from typing import TypeGuard
9
6
  from tortoise.backends.asyncpg import AsyncpgDBClient
10
7
  from x_model import init_db
11
8
  from xync_client.Abc.Base import BaseClient, DictOfDicts, ListOfDicts, FlatDict, MapOfIdsList
@@ -16,11 +13,9 @@ from xync_client.loader import PG_DSN
16
13
 
17
14
  class BaseTest:
18
15
  # loop: AbstractEventLoop
19
-
20
16
  # @pytest.fixture(scope="session", autouse=True)
21
17
  # def event_loop_policy(self):
22
18
  # return uvloop.EventLoopPolicy()
23
-
24
19
  @pytest.fixture(scope="session", autouse=True)
25
20
  async def cn(self) -> AsyncpgDBClient:
26
21
  cn: AsyncpgDBClient = await init_db(PG_DSN, models, True)
@@ -37,12 +32,24 @@ class BaseTest:
37
32
  return False
38
33
  return all(isinstance(k, int | str) and isinstance(v, dict) for k, v in dct.items())
39
34
 
35
+ @staticmethod
36
+ def is_dict_of_objects(dct: dict, typ: type, not_empty: bool = True) -> TypeGuard[dict]: # todo: Generic
37
+ if not_empty and not len(dct):
38
+ return False
39
+ return all(isinstance(k, int | str) and isinstance(v, typ) for k, v in dct.items())
40
+
40
41
  @staticmethod
41
42
  def is_list_of_dicts(lst: ListOfDicts, not_empty: bool = True) -> TypeGuard[ListOfDicts]:
42
43
  if not_empty and not len(lst):
43
44
  return False
44
45
  return all(isinstance(el, dict) for el in lst)
45
46
 
47
+ @staticmethod
48
+ def is_list_of_objects(lst: list, typ: type, not_empty: bool = True) -> TypeGuard[list]:
49
+ if not_empty and not len(lst):
50
+ return False
51
+ return all(isinstance(el, typ) for el in lst)
52
+
46
53
  @staticmethod
47
54
  def is_flat_dict(dct: FlatDict, not_empty: bool = True) -> TypeGuard[FlatDict]:
48
55
  if not_empty and not len(dct):
@@ -2,11 +2,10 @@ import logging
2
2
  import re
3
3
  from abc import abstractmethod
4
4
 
5
- from xync_schema.pydantic import AdPydIn, PmPyd
6
-
5
+ from xync_schema.pydantic import AdPydIn, PmPyd, BaseAd
7
6
  from xync_schema.models import Ex, Coin, Cur, Pm, Pmex, Curex, Pmcur, Pmcurex, Coinex, PmexBank, Ad
8
7
 
9
- from xync_client.Abc.Base import BaseClient, DictOfDicts, FlatDict, ListOfDicts, MapOfIdsList
8
+ from xync_client.Abc.Base import BaseClient, DictOfDicts, FlatDict, MapOfIdsList
10
9
 
11
10
 
12
11
  class BaseExClient(BaseClient):
@@ -55,9 +54,17 @@ class BaseExClient(BaseClient):
55
54
  @abstractmethod
56
55
  async def ads(
57
56
  self, coin_exid: str, cur_exid: str, is_sell: bool, pm_exids: list[str | int] = None, amount: int = None
58
- ) -> ListOfDicts: # {ad.id: ad}
57
+ ) -> list[BaseAd]: # {ad.id: ad}
59
58
  ...
60
59
 
60
+ # 42: Объява по id
61
+ @abstractmethod
62
+ async def ad(self, ad_id: int) -> BaseAd: ...
63
+
64
+ # Преобразрование объекта объявления из формата биржи в формат xync
65
+ @abstractmethod
66
+ async def _ad_epyd2pydin(self, ad: BaseAd) -> AdPydIn: ...
67
+
61
68
  def _pmnorm(self, s: str) -> str:
62
69
  def get_and_remove_acro(title: str) -> str:
63
70
  acr = "".join(word[0] for word in title.split(" ") if len(word) > 1 and word.istitle())
@@ -191,8 +198,8 @@ class BaseExClient(BaseClient):
191
198
  await Coinex.bulk_create(coinexs, update_fields=["minimum"], on_conflict=["coin_id", "ex_id"])
192
199
 
193
200
  # Сохранение чужого объявления (с Pm-ами) в бд
194
- @staticmethod
195
- async def set_ad(ad: AdPydIn) -> Ad:
196
- ad_db, _ = await Ad.update_or_create(ad.model_dump(exclude_none=True), id=ad.id)
197
- await ad_db.pms.add(*ad.payMeths)
201
+ async def set_ad(self, ad: BaseAd) -> Ad:
202
+ adx = await self._ad_epyd2pydin(ad)
203
+ ad_db, _ = await Ad.update_or_create(adx.model_dump(exclude_none=True), id=adx.id)
204
+ await ad_db.pms.add(*adx.payMeths)
198
205
  return ad_db
@@ -71,6 +71,7 @@ class ExClient(BaseExClient, AuthClient):
71
71
  pairs = {cur: set(coins.values()) for cur in curs.values()}
72
72
  return pairs
73
73
 
74
+ # 42: Объява по id
74
75
  async def ad(self, ad_id: int) -> AdFullEpyd:
75
76
  ad = await self._post("/p2p/public-api/v2/offer/get", {"offerId": ad_id})
76
77
  return AdFullEpyd(**ad["data"])
@@ -90,7 +91,7 @@ class ExClient(BaseExClient, AuthClient):
90
91
  ads = await self._post("/p2p/public-api/v2/offer/depth-of-market/", params, "data")
91
92
  return [AdEpyd(**ad) for ad in ads]
92
93
 
93
- async def ad_epyd2xpyd(self, ad: AdEpyd | AdFullEpyd) -> AdPydIn:
94
+ async def _ad_epyd2pydin(self, ad: AdEpyd | AdFullEpyd) -> AdPydIn:
94
95
  coin = await Coin.get_or_create_by_name(ad.price.baseCurrencyCode)
95
96
  cur = await Cur.get_or_create_by_name(ad.price.quoteCurrencyCode)
96
97
  pair, _ = await Pair.get_or_create(coin=coin, cur=cur, ex=self.ex)
@@ -120,12 +121,10 @@ async def _test():
120
121
  await cl.set_coinexs()
121
122
  ads: list[AdEpyd] = await cl.ads("USDT", "RUB", False)
122
123
  ad: AdFullEpyd = await cl.ad(ads[0].id)
123
- adx: AdPydIn = await cl.ad_epyd2xpyd(ad)
124
- await cl.set_ad(adx)
124
+ await cl.set_ad(ad)
125
125
  ads: list[AdEpyd] = await cl.ads("USDT", "RUB", True)
126
126
  ad: AdEpyd = ads[1]
127
- adx: AdPydIn = await cl.ad_epyd2xpyd(ad)
128
- await cl.set_ad(adx)
127
+ await cl.set_ad(ad)
129
128
  await cl.close()
130
129
 
131
130
 
@@ -1,5 +1,6 @@
1
1
  from typing import Literal
2
2
  from pydantic import BaseModel
3
+ from xync_schema.pydantic import BaseAd
3
4
 
4
5
 
5
6
  class UserStatistics(BaseModel):
@@ -135,8 +136,7 @@ class _PaymentMethodsTrait:
135
136
  paymentMethods: list[PmEpydRoot]
136
137
 
137
138
 
138
- class __BaseCommonAd(BaseModel):
139
- id: int | None = None
139
+ class __BaseCommonAd(BaseAd):
140
140
  type: Literal["PURCHASE", "SALE"]
141
141
  price: Price
142
142
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: xync-client
3
- Version: 0.0.25.dev3
3
+ Version: 0.0.25.dev4
4
4
  Author-email: Mike Artemiev <mixartemev@gmail.com>
5
5
  Project-URL: Homepage, https://gitlab.com/XyncNet/client
6
6
  Project-URL: Repository, https://gitlab.com/XyncNet/client