xync-client 0.0.11.dev14__tar.gz → 0.0.11.dev18__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 (67) hide show
  1. {xync_client-0.0.11.dev14/xync_client.egg-info → xync_client-0.0.11.dev18}/PKG-INFO +1 -1
  2. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/README.md +2 -0
  3. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/pyproject.toml +1 -1
  4. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/tests/Abc/BaseTest.py +8 -5
  5. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/tests/TestEx.py +7 -5
  6. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/Abc/Agent.py +8 -3
  7. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/BingX/base.py +3 -1
  8. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/BingX/ex.py +2 -1
  9. xync_client-0.0.11.dev14/xync_client/Bybit/ex.py → xync_client-0.0.11.dev18/xync_client/Bybit/agent.py +28 -59
  10. xync_client-0.0.11.dev18/xync_client/Bybit/ex.py +64 -0
  11. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/Gate/ex.py +24 -19
  12. xync_client-0.0.11.dev18/xync_client/Htx/agent.py +115 -0
  13. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/Htx/ex.py +3 -0
  14. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/TgWallet/auth.py +2 -0
  15. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18/xync_client.egg-info}/PKG-INFO +1 -1
  16. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client.egg-info/SOURCES.txt +1 -0
  17. xync_client-0.0.11.dev14/xync_client/Htx/agent.py +0 -18
  18. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/.env.sample +0 -0
  19. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/.gitignore +0 -0
  20. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/.pre-commit-config.yaml +0 -0
  21. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/makefile +0 -0
  22. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/setup.cfg +0 -0
  23. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/tests/Abc/AgentTest.py +0 -0
  24. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/tests/Abc/OrderTest.py +0 -0
  25. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/tests/Binance/test_binance.py +0 -0
  26. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/tests/Bybit/test_bybit.py +0 -0
  27. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/tests/Bybit/test_bybit_p2p.py +0 -0
  28. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/tests/Gate/test_gate.py +0 -0
  29. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/tests/Htx/test_htx_p2p.py +0 -0
  30. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/tests/__init__.py +0 -0
  31. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/tests/_test_ex.py +0 -0
  32. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/Abc/Auth.py +0 -0
  33. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/Abc/Base.py +0 -0
  34. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/Abc/Ex.py +0 -0
  35. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/Abc/Order.py +0 -0
  36. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/Binance/__init__.py +0 -0
  37. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/Binance/binance_async.py +0 -0
  38. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/Binance/earn_api.py +0 -0
  39. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/Binance/ex.py +0 -0
  40. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/Binance/exceptions.py +0 -0
  41. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/Binance/sapi.py +0 -0
  42. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/Binance/web_c2c.py +0 -0
  43. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/BingX/__init__.py +0 -0
  44. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/BingX/req.mjs +0 -0
  45. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/BingX/sign.js +0 -0
  46. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/BingX/test/main.py +0 -0
  47. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/BitGet/__init__.py +0 -0
  48. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/BitGet/agent.py +0 -0
  49. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/BitGet/ex.py +0 -0
  50. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/BitGet/req.mjs +0 -0
  51. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/Bybit/web_earn.py +0 -0
  52. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/Bybit/web_p2p.py +0 -0
  53. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/Gate/premarket.py +0 -0
  54. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/Htx/earn.py +0 -0
  55. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/KuCoin/pub.py +0 -0
  56. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/KuCoin/web.py +0 -0
  57. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/Okx/ex.py +0 -0
  58. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/TgWallet/agent.py +0 -0
  59. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/TgWallet/ex.py +0 -0
  60. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/TgWallet/order.py +0 -0
  61. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/TgWallet/pyro.py +0 -0
  62. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/TgWallet/web.py +0 -0
  63. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/__init__.py +0 -0
  64. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client/loader.py +0 -0
  65. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client.egg-info/dependency_links.txt +0 -0
  66. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client.egg-info/requires.txt +0 -0
  67. {xync_client-0.0.11.dev14 → xync_client-0.0.11.dev18}/xync_client.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: xync-client
3
- Version: 0.0.11.dev14
3
+ Version: 0.0.11.dev18
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
@@ -159,3 +159,5 @@ classDef red stroke:#f00
159
159
  - 36N: Получение сообщения от юзера `get_user_msg => (msg:str, file=None)`
160
160
  - 37N: Получение уведомления о (раз)блокировке юзером `got_blocked => is_blocked:bool`
161
161
  - 38N: Получение уведомления о полученном отзыве `got_rated => (user_id:int, order_id:int)`
162
+
163
+ - 39: Получить балансы моих монет: `my_assets() => list[Asset]`
@@ -44,4 +44,4 @@ line-length = 120
44
44
 
45
45
  [tool.pytest.ini_options]
46
46
  asyncio_mode = "auto"
47
- asyncio_default_fixture_loop_scope = "class" # , "session", "module", "package", "function"
47
+ asyncio_default_fixture_loop_scope = "session" # , "class", "module", "package", "function"
@@ -1,8 +1,11 @@
1
1
  from abc import abstractmethod
2
- from asyncio import AbstractEventLoop
2
+
3
+ # from asyncio import AbstractEventLoop
3
4
  from typing import TypeGuard
4
5
 
5
6
  import pytest
7
+
8
+ # import uvloop
6
9
  from tortoise.backends.asyncpg import AsyncpgDBClient
7
10
  from x_model import init_db
8
11
  from xync_client.Abc.Base import BaseClient, DictOfDicts, ListOfDicts, FlatDict, MapOfIdsList
@@ -12,20 +15,20 @@ from xync_client.loader import PG_DSN
12
15
 
13
16
 
14
17
  class BaseTest:
15
- loop: AbstractEventLoop
18
+ # loop: AbstractEventLoop
16
19
 
17
- # @pytest.fixture(scope="class", autouse=True)
20
+ # @pytest.fixture(scope="session", autouse=True)
18
21
  # def event_loop_policy(self):
19
22
  # return uvloop.EventLoopPolicy()
20
23
 
21
- @pytest.fixture(scope="class", autouse=True)
24
+ @pytest.fixture(scope="session", autouse=True)
22
25
  async def cn(self) -> AsyncpgDBClient:
23
26
  cn: AsyncpgDBClient = await init_db(PG_DSN, models, True)
24
27
  yield cn
25
28
  await cn.close()
26
29
 
27
30
  @abstractmethod
28
- @pytest.fixture(scope="class")
31
+ @pytest.fixture(scope="session")
29
32
  async def clients(self) -> list[BaseClient]: ...
30
33
 
31
34
  @staticmethod
@@ -2,15 +2,16 @@ import logging
2
2
 
3
3
  import pytest
4
4
  from xync_schema.enums import ExStatus, ExType, ExAction
5
- from xync_schema.models import Ex, TestEx as TestExs
5
+ from xync_schema.models import Ex, TestEx as ExTest
6
6
 
7
7
  from tests.Abc.BaseTest import BaseTest
8
8
  from xync_client.Abc.Base import BaseClient, DictOfDicts, FlatDict
9
9
  from xync_client.Abc.Ex import BaseExClient
10
10
 
11
11
 
12
+ @pytest.mark.asyncio(loop_scope="session")
12
13
  class TestEx(BaseTest):
13
- @pytest.fixture(scope="class")
14
+ @pytest.fixture
14
15
  async def clients(self) -> list[BaseClient]:
15
16
  exs = await Ex.filter(status__gt=ExStatus.plan)
16
17
  [await ex.fetch_related("agents") for ex in exs if ex.type_ == ExType.tg]
@@ -22,7 +23,7 @@ class TestEx(BaseTest):
22
23
  async def test_pms(self, clients: list[BaseExClient]):
23
24
  for client in clients:
24
25
  pms: DictOfDicts = await client.pms()
25
- t, _ = await TestExs.update_or_create({"ok": self.is_dict_of_dicts(pms)}, ex=client.ex, action=ExAction.pms)
26
+ t, _ = await ExTest.update_or_create({"ok": self.is_dict_of_dicts(pms)}, ex=client.ex, action=ExAction.pms)
26
27
  assert t.ok, "No pms"
27
28
  logging.info(f"{client.ex.name}:{ExAction.pms.name} - ok")
28
29
 
@@ -30,7 +31,8 @@ class TestEx(BaseTest):
30
31
  async def test_curs(self, clients: list[BaseExClient]):
31
32
  for client in clients:
32
33
  curs: FlatDict = await client.curs()
33
- t, _ = await TestExs.update_or_create({"ok": self.is_flat_dict(curs)}, ex=client.ex, action=ExAction.curs)
34
+ ok = self.is_flat_dict(curs)
35
+ t, _ = await ExTest.update_or_create({"ok": ok}, ex=client.ex, action=ExAction.curs)
34
36
  assert t.ok, "No curs"
35
37
  logging.info(f"{client.ex.name}:{ExAction.pms.name} - ok")
36
38
 
@@ -39,6 +41,6 @@ class TestEx(BaseTest):
39
41
  for client in clients:
40
42
  cur_pms: DictOfDicts = await client.cur_pms_map()
41
43
  ok = self.is_dict_of_dicts(cur_pms)
42
- t, _ = await TestExs.update_or_create({"ok": ok}, ex=client.ex, action=ExAction.cur_pms_map)
44
+ t, _ = await ExTest.update_or_create({"ok": ok}, ex=client.ex, action=ExAction.cur_pms_map)
43
45
  assert t.ok, "No pms for cur"
44
46
  logging.info(f"{client.ex.name}:{ExAction.pms.name} - ok")
@@ -1,7 +1,8 @@
1
1
  from abc import abstractmethod
2
2
 
3
+ from xync_client.Abc.Base import ListOfDicts
4
+
3
5
  from xync_client.Abc.Auth import BaseAuthClient
4
- from xync_schema.enums import PmType
5
6
  from xync_schema.models import OrderStatus, Coin, Cur, Order, Pm, Ad, AdStatus, Fiat
6
7
  from xync_schema.pydantic import FiatNew
7
8
 
@@ -23,7 +24,7 @@ class BaseAgentClient(BaseAuthClient):
23
24
  # # # Fiat
24
25
  # 25: Список реквизитов моих платежных методов
25
26
  @abstractmethod
26
- async def my_fiats(self, cur: Cur = None) -> list[dict]: ...
27
+ async def my_fiats(self, cur: Cur = None) -> ListOfDicts: ...
27
28
 
28
29
  # 26: Создание
29
30
  @abstractmethod
@@ -31,7 +32,7 @@ class BaseAgentClient(BaseAuthClient):
31
32
 
32
33
  # 27: Редактирование
33
34
  @abstractmethod
34
- async def fiat_upd(self, detail: str = None, type_: PmType = None) -> bool: ...
35
+ async def fiat_upd(self, fiat_id: int, detail: str, name: str = None) -> bool: ...
35
36
 
36
37
  # 28: Удаление
37
38
  @abstractmethod
@@ -99,3 +100,7 @@ class BaseAgentClient(BaseAuthClient):
99
100
  # 38: Поставить отзыв юзеру
100
101
  @abstractmethod
101
102
  async def rate_user(self, positive: bool) -> bool: ...
103
+
104
+ # 39: Балансы моих монет
105
+ @abstractmethod
106
+ async def my_assets(self) -> dict: ...
@@ -1,3 +1,4 @@
1
+ import os
1
2
  import subprocess
2
3
  from datetime import datetime
3
4
  from json import dumps
@@ -11,7 +12,8 @@ class BaseBingXClient(BaseClient):
11
12
  traceid = str(uuid4()).replace("-", "")
12
13
  now = str(int(datetime.now().timestamp() * 1000))
13
14
  payload = dumps(_payload, separators=(",", ":"), sort_keys=True) if _payload else "{}"
14
- p = subprocess.Popen(["node", "../xync_client/BingX/req.mjs", now, traceid, payload], stdout=subprocess.PIPE)
15
+ pref = "../xync_client/BingX/" if os.getcwd().split("/")[-1] == "tests" else ""
16
+ p = subprocess.Popen(["node", pref + "req.mjs", now, traceid, payload], stdout=subprocess.PIPE)
15
17
  sign = p.stdout.read().decode().strip()
16
18
  return {
17
19
  "sign": sign,
@@ -54,7 +54,8 @@ async def main():
54
54
  _ = await init_db(PG_DSN, models, True)
55
55
  bg = await Ex.get(name="BingX")
56
56
  cl = ExClient(bg)
57
- await cl.pms()
57
+ await cl.curs()
58
+ # pms = await cl.pms()
58
59
  await cl.close()
59
60
 
60
61
 
@@ -2,8 +2,10 @@ from enum import IntEnum
2
2
  from time import sleep
3
3
 
4
4
  import pyotp
5
- from x_client.aiohttp import Client
5
+ from xync_client.Abc.Base import FlatDict
6
+ from xync_schema.models import Cur
6
7
 
8
+ from xync_client.Abc.Agent import BaseAgentClient
7
9
  from xync_client.loader import BYT2FA
8
10
 
9
11
 
@@ -16,10 +18,9 @@ class AdsStatus(IntEnum):
16
18
  WORKING = 1
17
19
 
18
20
 
19
- class ExClient(Client): # Bybit client
21
+ class ExClient(BaseAgentClient): # Bybit client
20
22
  host = "api2.bybit.com"
21
-
22
- pub_header = {"cookie": ";"} # rewrite token for public methods
23
+ headers = {"cookie": ";"} # rewrite token for public methods
23
24
 
24
25
  last_ad_id: list[str] = []
25
26
  create_ad_body = {
@@ -79,49 +80,15 @@ class ExClient(Client): # Bybit client
79
80
  "securityRiskToken": "",
80
81
  }
81
82
 
82
- """ PUBLIC METHS """
83
-
84
- def get_ads(self, coin: str, cur: str, sell: bool = False, amount: int = None, payment: list[str] = None) -> list:
85
- data = {
86
- "userId": "",
87
- "tokenId": coin,
88
- "currencyId": cur,
89
- "payment": payment or [],
90
- "side": "0" if sell else "1",
91
- "size": "10",
92
- "page": "1",
93
- "amount": str(amount) if amount else "",
94
- "authMaker": False,
95
- "canTrade": False,
96
- }
97
- ads = self._post("/fiat/otc/item/online/", data, self.pub_header)
98
- return ads["result"]["items"]
99
-
100
- async def get_config(self):
101
- resp = await self._get("/fiat/p2p/config/initial", self.pub_header)
102
- return resp["result"] # todo: tokens, pairs, ...
103
-
104
- async def curs(self):
105
- config = await self.get_config()
106
- return config["symbols"]
107
-
108
- def get_coins(self):
109
- coins = self._get("/spot/api/basic/symbol_list", self.pub_header)
110
- return coins
111
-
112
- def get_payment_methods(self):
113
- pms = self._post("/fiat/otc/configuration/queryAllPaymentList/", headers=self.pub_header)
114
- return pms
115
-
116
83
  """ Private METHs"""
117
84
 
118
- def create_payment_method(self, payment_type: int, real_name: str, account_number: str) -> dict:
85
+ def fiat_new(self, payment_type: int, real_name: str, account_number: str) -> FlatDict:
119
86
  method1 = self._post(
120
87
  "/fiat/otc/user/payment/new_create",
121
88
  {"paymentType": payment_type, "realName": real_name, "accountNo": account_number, "securityRiskToken": ""},
122
89
  )
123
90
  if srt := method1["result"]["securityRiskToken"]:
124
- self.check_2fa(srt)
91
+ self._check_2fa(srt)
125
92
  method2 = self._post(
126
93
  "/fiat/otc/user/payment/new_create",
127
94
  {
@@ -142,24 +109,26 @@ class ExClient(Client): # Bybit client
142
109
  return fiat
143
110
  return list_methods[1]
144
111
 
145
- def update_payment_method(self, real_name: str, account_number: str, fiat_id: int = None) -> dict:
112
+ # 27
113
+ def fiat_upd(self, fiat_id: int, detail: str, name: str = None) -> dict:
146
114
  fiat = self.get_payment_method(fiat_id)
147
- fiat["realName"] = real_name
148
- fiat["accountNo"] = account_number
149
- result = self._post("/fiat/otc/user/payment/new_update", fiat)
115
+ fiat["realName"] = name
116
+ fiat["accountNo"] = detail
117
+ result = await self._post("/fiat/otc/user/payment/new_update", fiat)
150
118
  srt = result["result"]["securityRiskToken"]
151
- self.check_2fa(srt)
119
+ self._check_2fa(srt)
152
120
  fiat["securityRiskToken"] = srt
153
- result2 = self._post("/fiat/otc/user/payment/new_update", fiat)
121
+ result2 = await self._post("/fiat/otc/user/payment/new_update", fiat)
154
122
  return result2
155
123
 
156
- def delete_payment_method(self, ids: str) -> dict:
157
- data = {"id": ids, "securityRiskToken": ""}
158
- method = self._post("/fiat/otc/user/payment/new_delete", data)
124
+ # 28
125
+ def fiat_del(self, fiat_id: int) -> dict:
126
+ data = {"id": fiat_id, "securityRiskToken": ""}
127
+ method = await self._post("/fiat/otc/user/payment/new_delete", data)
159
128
  srt = method["result"]["securityRiskToken"]
160
- self.check_2fa(srt)
129
+ self._check_2fa(srt)
161
130
  data["securityRiskToken"] = srt
162
- delete = self._post("/fiat/otc/user/payment/new_delete", data)
131
+ delete = await self._post("/fiat/otc/user/payment/new_delete", data)
163
132
  return delete
164
133
 
165
134
  def switch_ads(self, new_status: AdsStatus) -> dict:
@@ -176,8 +145,8 @@ class ExClient(Client): # Bybit client
176
145
  ads = [ad for ad in list_ads if set(ad["payments"]) - {"5", "51"}]
177
146
  return float(ads[0]["price"])
178
147
 
179
- def get_user_pay_methods(self):
180
- upm = self._post("/fiat/otc/user/payment/list")
148
+ def my_fiats(self, cur: Cur = None):
149
+ upm = await self._post("/fiat/otc/user/payment/list")
181
150
  return upm["result"]
182
151
 
183
152
  def get_user_ads(self, active: bool = True) -> list:
@@ -191,7 +160,7 @@ class ExClient(Client): # Bybit client
191
160
  security_risk_token = data["result"]["securityRiskToken"]
192
161
  return security_risk_token
193
162
 
194
- def check_2fa(self, risk_token):
163
+ def _check_2fa(self, risk_token):
195
164
  # 2fa code
196
165
  bybit_secret = BYT2FA
197
166
  totp = pyotp.TOTP(bybit_secret)
@@ -203,7 +172,7 @@ class ExClient(Client): # Bybit client
203
172
  if res["ret_msg"] != "success":
204
173
  print("Wrong 2fa, wait 5 secs and retry..")
205
174
  sleep(5)
206
- self.check_2fa(risk_token)
175
+ self._check_2fa(risk_token)
207
176
  return res
208
177
 
209
178
  def post_ad(self, risk_token: str):
@@ -213,8 +182,8 @@ class ExClient(Client): # Bybit client
213
182
 
214
183
  # создание объявлений
215
184
  def post_create_ad(self, token: str):
216
- result_check_2fa = self.check_2fa(token)
217
- assert result_check_2fa["ret_msg"] == "success", "2FA code wrong"
185
+ result__check_2fa = self._check_2fa(token)
186
+ assert result__check_2fa["ret_msg"] == "success", "2FA code wrong"
218
187
 
219
188
  result_add_ad = self._post_ad(token)
220
189
  if result_add_ad["ret_msg"] != "SUCCESS":
@@ -230,8 +199,8 @@ class ExClient(Client): # Bybit client
230
199
  return security_risk_token
231
200
 
232
201
  def post_update_ad(self, token):
233
- result_check_2fa = self.check_2fa(token)
234
- assert result_check_2fa["ret_msg"] == "success", "2FA code wrong"
202
+ result__check_2fa = self._check_2fa(token)
203
+ assert result__check_2fa["ret_msg"] == "success", "2FA code wrong"
235
204
 
236
205
  result_update_ad = self.update_ad(token)
237
206
  if result_update_ad["ret_msg"] != "SUCCESS":
@@ -0,0 +1,64 @@
1
+ import json
2
+ from enum import IntEnum
3
+
4
+ from xync_client.Abc.Base import ListOfDicts, MapOfIdsList, DictOfDicts, FlatDict
5
+ from xync_client.Abc.Ex import BaseExClient
6
+
7
+
8
+ class AdsStatus(IntEnum):
9
+ REST = 0
10
+ WORKING = 1
11
+
12
+
13
+ class ExClient(BaseExClient): # Bybit client
14
+ host = "api2.bybit.com"
15
+ headers = {"cookie": ";"} # rewrite token for public methods
16
+
17
+ async def _get_config(self):
18
+ resp = await self._get("/fiat/p2p/config/initial")
19
+ return resp["result"] # todo: tokens, pairs, ...
20
+
21
+ # 20: Список всех платежных методов на бирже
22
+ async def pms(self) -> DictOfDicts:
23
+ pms = await self._post("/fiat/otc/configuration/queryAllPaymentList/")
24
+ pms = pms["result"]["paymentConfigVo"]
25
+ return {
26
+ pm["paymentType"]: {
27
+ "name": pm["paymentName"],
28
+ }
29
+ for pm in pms
30
+ }
31
+
32
+ # 21: Список поддерживаемых валют
33
+ async def curs(self) -> FlatDict:
34
+ config = await self._get_config()
35
+ return {c["id"]: c["currencyId"] for c in config["symbols"]}
36
+
37
+ # 22: Список платежных методов по каждой валюте
38
+ async def cur_pms_map(self) -> MapOfIdsList:
39
+ pms = await self._post("/fiat/otc/configuration/queryAllPaymentList/")
40
+ return json.loads(pms["result"]["currencyPaymentIdMap"])
41
+
42
+ # 23: Список торгуемых монет (с ограничениям по валютам, если есть)
43
+ async def coins(self) -> FlatDict:
44
+ coins = await self._get("/spot/api/basic/symbol_list")
45
+ return coins
46
+
47
+ # 24: Список объяв по (buy/sell, cur, coin, pm)
48
+ async def ads(
49
+ self, coin_exid: str, cur_exid: str, is_sell: bool, pm_exids: list[str | int] = None, amount: int = None
50
+ ) -> ListOfDicts:
51
+ data = {
52
+ "userId": "",
53
+ "tokenId": coin_exid,
54
+ "currencyId": cur_exid,
55
+ "payment": pm_exids or [],
56
+ "side": "0" if is_sell else "1",
57
+ "size": "10",
58
+ "page": "1",
59
+ "amount": str(amount) if amount else "",
60
+ "authMaker": False,
61
+ "canTrade": False,
62
+ }
63
+ ads = await self._post("/fiat/otc/item/online/", data)
64
+ return ads["result"]["items"]
@@ -1,13 +1,13 @@
1
1
  import re
2
- from asyncio import run
2
+ from asyncio import run, sleep
3
3
  from json import JSONDecoder
4
4
 
5
5
  from bs4 import BeautifulSoup, Script
6
6
  from x_model import init_db
7
7
  from xync_schema import models
8
- from xync_schema.models import Coin, Cur, Pm, Ad, Ex, Curex
8
+ from xync_schema.models import Coin, Cur, Pm, Ad, Ex
9
9
 
10
- from xync_client.Abc.Base import MapOfIdsList
10
+ from xync_client.Abc.Base import MapOfIdsList, DictOfDicts, FlatDict
11
11
  from xync_client.Abc.Ex import BaseExClient
12
12
  from xync_client.loader import PG_DSN
13
13
 
@@ -16,19 +16,19 @@ class ExClient(BaseExClient):
16
16
  async def cur_pms_map(self) -> MapOfIdsList:
17
17
  pass
18
18
 
19
- async def curs(self) -> list[Cur]:
19
+ async def curs(self) -> FlatDict:
20
20
  curs = await self._post("/json_svr/buy_crypto_fiat_setting")
21
- curs = [cur["fiat"] for cur in curs if cur["p2p"]]
22
- curexs = [Curex(cur=c, ex=self.ex) for c in curs]
23
- await Curex.bulk_create(curexs, ignore_conflicts=True)
21
+ curs = {cur["fiat"]: cur["fiat"] for cur in curs["datas"] if cur["p2p"]}
24
22
  return curs
25
23
 
26
24
  async def coins(self, cur: Cur = None) -> list[Coin]: ...
27
25
 
28
- async def pms(self, cur: Cur = None) -> list[Pm]:
26
+ async def pms(self, cur: Cur = None) -> DictOfDicts:
27
+ await sleep(1)
29
28
  doc = await self._get("/p2p")
29
+ await sleep(1)
30
30
  soup = BeautifulSoup(doc, "html.parser")
31
- script: Script = soup.body.find_all("script")[14]
31
+ script: Script = soup.body.find_all("script")[17] # 17-th not stable
32
32
  strng = (
33
33
  script.get_text(strip=True)
34
34
  .replace("\n", "")
@@ -43,15 +43,19 @@ class ExClient(BaseExClient):
43
43
  pattern = r"payment_settings:\s{1}(\{.*?\}),paymentIdMap:"
44
44
  match = re.search(pattern, strng.replace(",}", "}").replace(",]", "]"), re.DOTALL)
45
45
  res = match.group(1)
46
- _ = JSONDecoder(strict=False).decode(res)
47
- pmcurs = {
48
- cur.ticker: (await self._get("/v3/c2c/configs/receipt/templates", {"quoteCurrency": cur.ticker}))["data"]
49
- for cur in await self.curs()
46
+ pms = JSONDecoder(strict=False).decode(res)
47
+ return {
48
+ pm["index"]: {"name": pm["pay_name"], "logo": pm["image"], "identifier": idf, "type_": pm["base_type"]}
49
+ for idf, pm in pms.items()
50
50
  }
51
- pp = {}
52
- [[pp.update({p["paymentMethod"]: p["paymentMethodDescription"]}) for p in ps] for ps in pmcurs.values()]
53
- pp = {k: v for k, v in sorted(pp.items(), key=lambda x: x[0])}
54
- return pp
51
+ # pmcurs = {
52
+ # cur.ticker: (await self._get("/v3/c2c/configs/receipt/templates", {"quoteCurrency": cur.ticker}))["data"]
53
+ # for cur in await self.curs()
54
+ # }
55
+ # pp = {}
56
+ # [[pp.update({p["paymentMethod"]: p["paymentMethodDescription"]}) for p in ps] for ps in pmcurs.values()]
57
+ # pp = {k: v for k, v in sorted(pp.items(), key=lambda x: x[0])}
58
+ # return pp
55
59
 
56
60
  async def ads(self, coin: Coin, cur: Cur, is_sell: bool, pms: list[Pm] = None) -> list[Ad]:
57
61
  pass
@@ -61,9 +65,10 @@ async def main():
61
65
  _ = await init_db(PG_DSN, models, True)
62
66
  bg = await Ex.get(name="Gate")
63
67
  cl = ExClient(bg)
64
- # await cl.curs()
68
+ await cl.curs()
65
69
  # await cl.coins()
66
- await cl.pms()
70
+ pms = await cl.pms()
71
+ print(pms)
67
72
 
68
73
 
69
74
  if __name__ == "__main__":
@@ -0,0 +1,115 @@
1
+ from x_client.aiohttp import Client
2
+ from xync_schema.enums import AdStatus, PmType, OrderStatus
3
+ from xync_schema.models import Pm, Coin, Cur, Ad, Fiat, Order
4
+ from xync_schema.pydantic import FiatNew
5
+
6
+ from xync_client.Abc.Agent import BaseAgentClient
7
+
8
+ url_ads_req = "https://otc-cf.huobi.com/v1/data/trade-market"
9
+ url_ads_web = "https://www.huobi.com/en-us/fiat-crypto/trade/"
10
+ url_my_ads = "https://otc-api.trygofast.com/v1/data/trade-list?pageSize=50"
11
+ url_my_ad = "https://www.huobi.com/-/x/otc/v1/otc/trade/" # + id
12
+ url_my_bals = "https://www.huobi.com/-/x/otc/v1/capital/balance"
13
+ url_paccs = "https://www.huobi.com/-/x/otc/v1/user/receipt-account"
14
+
15
+
16
+ class Public(Client):
17
+ url_ads_web = "https://www.huobi.com/en-us/fiat-crypto/trade/"
18
+
19
+
20
+ class Private(BaseAgentClient):
21
+ # 0
22
+ async def get_orders(
23
+ self, stauts: OrderStatus = OrderStatus.created, coin: Coin = None, cur: Cur = None, is_sell: bool = None
24
+ ) -> list[Order]:
25
+ pass
26
+
27
+ async def order_request(self, ad_id: int, amount: float) -> dict:
28
+ pass
29
+
30
+ async def my_fiats(self, cur: Cur = None) -> list[dict]:
31
+ pass
32
+
33
+ async def fiat_new(self, fiat: FiatNew) -> Fiat.pyd():
34
+ pass
35
+
36
+ async def fiat_upd(self, detail: str = None, type_: PmType = None) -> bool:
37
+ pass
38
+
39
+ async def fiat_del(self, fiat_id: int) -> bool:
40
+ pass
41
+
42
+ async def my_ads(self) -> list[dict]:
43
+ res = await self._get(url_my_ads)
44
+ ads: [] = res["data"]
45
+ if (pages := res["totalPage"]) > 1:
46
+ for p in range(2, pages + 1):
47
+ ads += (await self._get(url_my_ads, {"currPage": p})).get("data", False)
48
+ return ads
49
+
50
+ async def ad_new(
51
+ self,
52
+ coin: Coin,
53
+ cur: Cur,
54
+ is_sell: bool,
55
+ pms: list[Pm],
56
+ price: float,
57
+ is_float: bool = True,
58
+ min_fiat: int = None,
59
+ details: str = None,
60
+ autoreply: str = None,
61
+ status: AdStatus = AdStatus.active,
62
+ ) -> Ad:
63
+ pass
64
+
65
+ async def ad_upd(
66
+ self,
67
+ pms: [Pm] = None,
68
+ price: float = None,
69
+ is_float: bool = None,
70
+ min_fiat: int = None,
71
+ details: str = None,
72
+ autoreply: str = None,
73
+ status: AdStatus = None,
74
+ ) -> bool:
75
+ pass
76
+
77
+ async def ad_del(self) -> bool:
78
+ pass
79
+
80
+ async def ad_switch(self) -> bool:
81
+ pass
82
+
83
+ async def ads_switch(self) -> bool:
84
+ pass
85
+
86
+ async def get_user(self, user_id) -> dict:
87
+ pass
88
+
89
+ async def send_user_msg(self, msg: str, file=None) -> bool:
90
+ pass
91
+
92
+ async def block_user(self, is_blocked: bool = True) -> bool:
93
+ pass
94
+
95
+ async def rate_user(self, positive: bool) -> bool:
96
+ pass
97
+
98
+ # 39
99
+ async def my_assets(self) -> dict:
100
+ assets = await self._get(url_my_bals)
101
+ return {c["coinId"]: c["total"] for c in assets["data"] if c["total"]}
102
+
103
+ async def _get_auth_hdrs(self) -> dict[str, str]:
104
+ pass
105
+
106
+ base_url = ""
107
+ middle_url = ""
108
+
109
+ htok: str = "Ev5lFfAvxDU2MA9BJ-Mc4U6zZG3Wb6qsp3Tx2fz6GIoY-uOP2m0-gvjE57ad1qDF"
110
+
111
+ url_ads_req = "https://otc-cf.huobi.com/v1/data/trade-market"
112
+ url_my_ads = "https://otc-api.trygofast.com/v1/data/trade-list?pageSize=50"
113
+ url_my_ad = "https://www.huobi.com/-/x/otc/v1/otc/trade/" # + id
114
+ url_my_bals = "https://www.huobi.com/-/x/otc/v1/capital/balance"
115
+ url_paccs = "https://www.huobi.com/-/x/otc/v1/user/receipt-account"
@@ -47,10 +47,12 @@ class ExClient(BaseExClient):
47
47
  wrong_pms = {4, 34, 498, 548, 20009, 20010} # , 212, 239, 363 # these ids not exist in pms
48
48
  return {c["currencyId"]: set(c["supportPayments"]) - wrong_pms for c in res["currency"] if c["supportPayments"]}
49
49
 
50
+ # 23: Список торгуемых монет
50
51
  async def coins(self) -> dict[int, str]:
51
52
  coins: list[dict] = (await self._coin_curs_pms())["coin"]
52
53
  return {c["coinId"]: c["coinCode"] for c in coins if c["coinType"] == 2}
53
54
 
55
+ # 24: Список объяв
54
56
  async def ads(self, coin: Coin, cur: Cur, is_sell: bool, pms: list[Pm] = None) -> list[Ad]:
55
57
  res = await self._coin_curs_pms()
56
58
  return res["country"]
@@ -65,6 +67,7 @@ async def main():
65
67
  _ = await init_db(PG_DSN, models, True)
66
68
  ex = await Ex.get(name="Htx")
67
69
  cl = ExClient(ex)
70
+ await cl.curs()
68
71
  await cl.set_pmcurexs()
69
72
  await cl.set_coinexs()
70
73
  await cl.close()
@@ -9,4 +9,6 @@ class AuthClient(BaseAuthClient):
9
9
  pyro = PyroClient(self.agent)
10
10
  init_data = await pyro.get_init_data()
11
11
  tokens = HttpClient("walletbot.me")._post("/api/v1/users/auth/", init_data)
12
+ self.agent.exid = tokens["user_id"]
13
+ await self.agent.save()
12
14
  return {"Wallet-Authorization": tokens["jwt"], "Authorization": "Bearer " + tokens["value"]}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: xync-client
3
- Version: 0.0.11.dev14
3
+ Version: 0.0.11.dev18
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
@@ -44,6 +44,7 @@ xync_client/BitGet/__init__.py
44
44
  xync_client/BitGet/agent.py
45
45
  xync_client/BitGet/ex.py
46
46
  xync_client/BitGet/req.mjs
47
+ xync_client/Bybit/agent.py
47
48
  xync_client/Bybit/ex.py
48
49
  xync_client/Bybit/web_earn.py
49
50
  xync_client/Bybit/web_p2p.py
@@ -1,18 +0,0 @@
1
- from x_client.aiohttp import Client
2
-
3
-
4
- class Public(Client):
5
- url_ads_web = "https://www.huobi.com/en-us/fiat-crypto/trade/"
6
-
7
-
8
- class Private(Client):
9
- base_url = ""
10
- middle_url = ""
11
-
12
- htok: str = "Ev5lFfAvxDU2MA9BJ-Mc4U6zZG3Wb6qsp3Tx2fz6GIoY-uOP2m0-gvjE57ad1qDF"
13
-
14
- url_ads_req = "https://otc-cf.huobi.com/v1/data/trade-market"
15
- url_my_ads = "https://otc-api.trygofast.com/v1/data/trade-list?pageSize=50"
16
- url_my_ad = "https://www.huobi.com/-/x/otc/v1/otc/trade/" # + id
17
- url_my_bals = "https://www.huobi.com/-/x/otc/v1/capital/balance"
18
- url_paccs = "https://www.huobi.com/-/x/otc/v1/user/receipt-account"