xync-client 0.0.11.dev12__tar.gz → 0.0.11.dev15__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.
- {xync_client-0.0.11.dev12/xync_client.egg-info → xync_client-0.0.11.dev15}/PKG-INFO +1 -1
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/README.md +2 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/pyproject.toml +1 -1
- xync_client-0.0.11.dev15/tests/Abc/AgentTest.py +17 -0
- xync_client-0.0.11.dev15/tests/Abc/BaseTest.py +56 -0
- xync_client-0.0.11.dev15/tests/TestEx.py +45 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/Abc/Agent.py +9 -4
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/Abc/Auth.py +7 -5
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/Binance/ex.py +4 -5
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/BingX/base.py +3 -1
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/BingX/ex.py +4 -3
- xync_client-0.0.11.dev15/xync_client/BingX/test/main.py +22 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/BitGet/agent.py +1 -1
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/BitGet/ex.py +27 -12
- xync_client-0.0.11.dev12/xync_client/Bybit/ex.py → xync_client-0.0.11.dev15/xync_client/Bybit/agent.py +28 -59
- xync_client-0.0.11.dev15/xync_client/Bybit/ex.py +58 -0
- xync_client-0.0.11.dev12/xync_client/Gate/pub.py → xync_client-0.0.11.dev15/xync_client/Gate/ex.py +4 -3
- xync_client-0.0.11.dev15/xync_client/Htx/agent.py +115 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/Htx/ex.py +7 -4
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/TgWallet/agent.py +6 -13
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/TgWallet/auth.py +2 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/TgWallet/ex.py +3 -2
- xync_client-0.0.11.dev15/xync_client/__init__.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15/xync_client.egg-info}/PKG-INFO +1 -1
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client.egg-info/SOURCES.txt +8 -6
- xync_client-0.0.11.dev12/xync_client/AbcTest/AgentTest.py +0 -13
- xync_client-0.0.11.dev12/xync_client/AbcTest/BaseTest.py +0 -42
- xync_client-0.0.11.dev12/xync_client/AbcTest/ExTest.py +0 -12
- xync_client-0.0.11.dev12/xync_client/BingX/test/main.py +0 -39
- xync_client-0.0.11.dev12/xync_client/Htx/agent.py +0 -18
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/.env.sample +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/.gitignore +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/.pre-commit-config.yaml +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/makefile +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/setup.cfg +0 -0
- {xync_client-0.0.11.dev12/xync_client/AbcTest → xync_client-0.0.11.dev15/tests/Abc}/OrderTest.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/tests/Binance/test_binance.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/tests/Bybit/test_bybit.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/tests/Bybit/test_bybit_p2p.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/tests/Gate/test_gate.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/tests/Htx/test_htx_p2p.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/tests/__init__.py +0 -0
- /xync_client-0.0.11.dev12/tests/test_ex.py → /xync_client-0.0.11.dev15/tests/_test_ex.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/Abc/Base.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/Abc/Ex.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/Abc/Order.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/Binance/__init__.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/Binance/binance_async.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/Binance/earn_api.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/Binance/exceptions.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/Binance/sapi.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/Binance/web_c2c.py +0 -0
- {xync_client-0.0.11.dev12/xync_client/BitGet → xync_client-0.0.11.dev15/xync_client/BingX}/__init__.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/BingX/req.mjs +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/BingX/sign.js +0 -0
- {xync_client-0.0.11.dev12/xync_client → xync_client-0.0.11.dev15/xync_client/BitGet}/__init__.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/BitGet/req.mjs +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/Bybit/web_earn.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/Bybit/web_p2p.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/Gate/premarket.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/Htx/earn.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/KuCoin/pub.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/KuCoin/web.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/Okx/ex.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/TgWallet/order.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/TgWallet/pyro.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/TgWallet/web.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client/loader.py +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client.egg-info/dependency_links.txt +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client.egg-info/requires.txt +0 -0
- {xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client.egg-info/top_level.txt +0 -0
|
@@ -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]`
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from tests.Abc.BaseTest import BaseTest
|
|
4
|
+
from xync_client.Abc.Agent import BaseAgentClient
|
|
5
|
+
from xync_client.Abc.Base import BaseClient
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AgentTest(BaseTest):
|
|
9
|
+
async def clients(self) -> list[BaseClient]:
|
|
10
|
+
pass
|
|
11
|
+
|
|
12
|
+
@pytest.fixture(scope="class", autouse=True)
|
|
13
|
+
async def cl(self) -> BaseAgentClient:
|
|
14
|
+
agent = (await self.ex).agents.filter(auth__not_isnull=True).first()
|
|
15
|
+
acl = BaseClient(agent)
|
|
16
|
+
yield acl
|
|
17
|
+
await acl.close()
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from abc import abstractmethod
|
|
2
|
+
|
|
3
|
+
# from asyncio import AbstractEventLoop
|
|
4
|
+
from typing import TypeGuard
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
|
|
8
|
+
# import uvloop
|
|
9
|
+
from tortoise.backends.asyncpg import AsyncpgDBClient
|
|
10
|
+
from x_model import init_db
|
|
11
|
+
from xync_client.Abc.Base import BaseClient, DictOfDicts, ListOfDicts, FlatDict, MapOfIdsList
|
|
12
|
+
from xync_schema import models
|
|
13
|
+
|
|
14
|
+
from xync_client.loader import PG_DSN
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class BaseTest:
|
|
18
|
+
# loop: AbstractEventLoop
|
|
19
|
+
|
|
20
|
+
# @pytest.fixture(scope="session", autouse=True)
|
|
21
|
+
# def event_loop_policy(self):
|
|
22
|
+
# return uvloop.EventLoopPolicy()
|
|
23
|
+
|
|
24
|
+
@pytest.fixture(scope="session", autouse=True)
|
|
25
|
+
async def cn(self) -> AsyncpgDBClient:
|
|
26
|
+
cn: AsyncpgDBClient = await init_db(PG_DSN, models, True)
|
|
27
|
+
yield cn
|
|
28
|
+
await cn.close()
|
|
29
|
+
|
|
30
|
+
@abstractmethod
|
|
31
|
+
@pytest.fixture(scope="session")
|
|
32
|
+
async def clients(self) -> list[BaseClient]: ...
|
|
33
|
+
|
|
34
|
+
@staticmethod
|
|
35
|
+
def is_dict_of_dicts(dct: DictOfDicts, not_empty: bool = True) -> TypeGuard[DictOfDicts]:
|
|
36
|
+
if not_empty and not len(dct):
|
|
37
|
+
return False
|
|
38
|
+
return all(isinstance(k, int | str) and isinstance(v, dict) for k, v in dct.items())
|
|
39
|
+
|
|
40
|
+
@staticmethod
|
|
41
|
+
def is_list_of_dicts(lst: ListOfDicts, not_empty: bool = True) -> TypeGuard[ListOfDicts]:
|
|
42
|
+
if not_empty and not len(lst):
|
|
43
|
+
return False
|
|
44
|
+
return all(isinstance(el, dict) for el in lst)
|
|
45
|
+
|
|
46
|
+
@staticmethod
|
|
47
|
+
def is_flat_dict(dct: FlatDict, not_empty: bool = True) -> TypeGuard[FlatDict]:
|
|
48
|
+
if not_empty and not len(dct):
|
|
49
|
+
return False
|
|
50
|
+
return all(isinstance(k, int | str) and isinstance(v, str) for k, v in dct.items())
|
|
51
|
+
|
|
52
|
+
@staticmethod
|
|
53
|
+
def is_map_of_ids(dct: MapOfIdsList, not_empty: bool = True) -> TypeGuard[MapOfIdsList]:
|
|
54
|
+
if not_empty and not len(dct):
|
|
55
|
+
return False
|
|
56
|
+
return all(isinstance(k, int | str) and isinstance(v, str) for k, v in dct.items())
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from xync_schema.enums import ExStatus, ExType, ExAction
|
|
5
|
+
from xync_schema.models import Ex, TestEx as ExTest
|
|
6
|
+
|
|
7
|
+
from tests.Abc.BaseTest import BaseTest
|
|
8
|
+
from xync_client.Abc.Base import BaseClient, DictOfDicts, FlatDict
|
|
9
|
+
from xync_client.Abc.Ex import BaseExClient
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@pytest.mark.asyncio(loop_scope="session")
|
|
13
|
+
class TestEx(BaseTest):
|
|
14
|
+
@pytest.fixture
|
|
15
|
+
async def clients(self) -> list[BaseClient]:
|
|
16
|
+
exs = await Ex.filter(status__gt=ExStatus.plan)
|
|
17
|
+
[await ex.fetch_related("agents") for ex in exs if ex.type_ == ExType.tg]
|
|
18
|
+
clients: list[BaseExClient] = [ex.client() for ex in exs]
|
|
19
|
+
yield clients
|
|
20
|
+
[await cl.close() for cl in clients]
|
|
21
|
+
|
|
22
|
+
# 20
|
|
23
|
+
async def test_pms(self, clients: list[BaseExClient]):
|
|
24
|
+
for client in clients:
|
|
25
|
+
pms: DictOfDicts = await client.pms()
|
|
26
|
+
t, _ = await ExTest.update_or_create({"ok": self.is_dict_of_dicts(pms)}, ex=client.ex, action=ExAction.pms)
|
|
27
|
+
assert t.ok, "No pms"
|
|
28
|
+
logging.info(f"{client.ex.name}:{ExAction.pms.name} - ok")
|
|
29
|
+
|
|
30
|
+
# 21
|
|
31
|
+
async def test_curs(self, clients: list[BaseExClient]):
|
|
32
|
+
for client in clients:
|
|
33
|
+
curs: FlatDict = await client.curs()
|
|
34
|
+
t, _ = await ExTest.update_or_create({"ok": self.is_flat_dict(curs)}, ex=client.ex, action=ExAction.curs)
|
|
35
|
+
assert t.ok, "No curs"
|
|
36
|
+
logging.info(f"{client.ex.name}:{ExAction.pms.name} - ok")
|
|
37
|
+
|
|
38
|
+
# 22
|
|
39
|
+
async def test_cur_pms_map(self, clients: list[BaseExClient]):
|
|
40
|
+
for client in clients:
|
|
41
|
+
cur_pms: DictOfDicts = await client.cur_pms_map()
|
|
42
|
+
ok = self.is_dict_of_dicts(cur_pms)
|
|
43
|
+
t, _ = await ExTest.update_or_create({"ok": ok}, ex=client.ex, action=ExAction.cur_pms_map)
|
|
44
|
+
assert t.ok, "No pms for cur"
|
|
45
|
+
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
|
|
|
@@ -10,7 +11,7 @@ class BaseAgentClient(BaseAuthClient):
|
|
|
10
11
|
# 0: Получшение ордеров в статусе status, по монете coin, в валюте coin, в направлении is_sell: bool
|
|
11
12
|
@abstractmethod
|
|
12
13
|
async def get_orders(
|
|
13
|
-
self, stauts: OrderStatus = OrderStatus.
|
|
14
|
+
self, stauts: OrderStatus = OrderStatus.created, coin: Coin = None, cur: Cur = None, is_sell: bool = None
|
|
14
15
|
) -> list[Order]: ...
|
|
15
16
|
|
|
16
17
|
# 1: [T] Получшение ордеров в статусе status, по монете coin, в валюте coin, в направлении is_sell: bool
|
|
@@ -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) ->
|
|
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
|
|
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: ...
|
|
@@ -3,21 +3,23 @@ from abc import abstractmethod
|
|
|
3
3
|
|
|
4
4
|
from aiohttp import ClientResponse
|
|
5
5
|
from aiohttp.http_exceptions import HttpProcessingError
|
|
6
|
-
from xync_schema.models import Agent
|
|
6
|
+
from xync_schema.models import Agent, Ex
|
|
7
7
|
|
|
8
8
|
from xync_client.Abc.Base import BaseClient
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class BaseAuthClient(BaseClient):
|
|
12
|
-
def __init__(self, agent: Agent):
|
|
13
|
-
|
|
14
|
-
self.agent = agent
|
|
12
|
+
def __init__(self, agent: Agent | Ex):
|
|
13
|
+
# dirty hack for multi-inheritance
|
|
14
|
+
self.agent = agent if isinstance(agent, Agent) else agent.agents[0]
|
|
15
|
+
ex = agent if isinstance(agent, Ex) else agent.ex
|
|
16
|
+
self.headers.update(self.agent.auth)
|
|
15
17
|
self.meth = {
|
|
16
18
|
"GET": self._get,
|
|
17
19
|
"POST": self._post,
|
|
18
20
|
"DELETE": self._delete,
|
|
19
21
|
}
|
|
20
|
-
super().__init__(
|
|
22
|
+
super().__init__(ex)
|
|
21
23
|
|
|
22
24
|
@abstractmethod
|
|
23
25
|
async def _get_auth_hdrs(self) -> dict[str, str]: ...
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
from xync_schema.enums import PmType
|
|
2
2
|
|
|
3
|
-
from xync_client.Abc.Ex import
|
|
4
|
-
from xync_client.Binance.sapi import Sapi
|
|
3
|
+
from xync_client.Abc.Ex import BaseExClient
|
|
5
4
|
from xync_schema.models import Ex
|
|
6
5
|
|
|
7
6
|
|
|
8
|
-
class
|
|
9
|
-
def __init__(self, ex: Ex
|
|
10
|
-
self.sapi = Sapi(*bkeys)
|
|
7
|
+
class ExClient(BaseExClient):
|
|
8
|
+
def __init__(self, ex: Ex):
|
|
9
|
+
# self.sapi = Sapi(*bkeys)
|
|
11
10
|
super().__init__(ex)
|
|
12
11
|
|
|
13
12
|
async def curs(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
|
-
|
|
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,
|
|
@@ -10,7 +10,7 @@ from xync_client.BingX.base import BaseBingXClient
|
|
|
10
10
|
from xync_client.loader import PG_DSN
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class
|
|
13
|
+
class ExClient(BaseExClient, BaseBingXClient):
|
|
14
14
|
headers: dict[str, str] = {
|
|
15
15
|
"app_version": "9.0.5",
|
|
16
16
|
"device_id": "ccfb6d50-b63b-11ef-b31f-ef1f76f67c4e",
|
|
@@ -53,9 +53,10 @@ class Client(BaseExClient, BaseBingXClient):
|
|
|
53
53
|
async def main():
|
|
54
54
|
_ = await init_db(PG_DSN, models, True)
|
|
55
55
|
bg = await Ex.get(name="BingX")
|
|
56
|
-
cl =
|
|
56
|
+
cl = ExClient(bg)
|
|
57
57
|
await cl.pms()
|
|
58
58
|
await cl.close()
|
|
59
59
|
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
if __name__ == "__main__":
|
|
62
|
+
run(main())
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
|
|
3
|
+
headers = {
|
|
4
|
+
"app_version": "8.10.0",
|
|
5
|
+
"device_id": "64a8c630-acc2-11ef-aa5e-9f6ee3baa1a5",
|
|
6
|
+
"lang": "ru-RU",
|
|
7
|
+
"platformid": "30",
|
|
8
|
+
"sign": "5679FBAAF1D0A199E6B0975616B44807220C5FC8824D41F0DE21D2261F2D8E18",
|
|
9
|
+
"timestamp": "1733496004073",
|
|
10
|
+
"traceid": "8557cddbfe574e07b36c3014b5773358",
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
params = {
|
|
14
|
+
"coinName": "USDT",
|
|
15
|
+
"tradeCoinName": "USD",
|
|
16
|
+
"type": "1",
|
|
17
|
+
"amount": "500",
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
response = requests.get("https://api-app.qq-os.com/api/fiat/v1/rapid-buy-integration", params=params, headers=headers)
|
|
21
|
+
|
|
22
|
+
print([i.get("paymentMethod")["name"] for i in response.json()["data"]["matchOptimalAdvertListVo"]["optimals"]])
|
|
@@ -19,7 +19,7 @@ class Client(BaseAgentClient):
|
|
|
19
19
|
super().__init__(agent)
|
|
20
20
|
|
|
21
21
|
async def get_orders(
|
|
22
|
-
self, stauts: OrderStatus = OrderStatus.
|
|
22
|
+
self, stauts: OrderStatus = OrderStatus.created, coin: Coin = None, cur: Cur = None, is_sell: bool = None
|
|
23
23
|
) -> list[Order]:
|
|
24
24
|
pass
|
|
25
25
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import os
|
|
2
3
|
import subprocess
|
|
3
4
|
from asyncio import run
|
|
4
5
|
|
|
@@ -7,12 +8,16 @@ from xync_client.Abc.Base import DictOfDicts
|
|
|
7
8
|
from xync_schema import models
|
|
8
9
|
from xync_schema.models import Cur, Ex
|
|
9
10
|
|
|
10
|
-
from xync_client.Abc.Ex import
|
|
11
|
+
from xync_client.Abc.Ex import BaseExClient
|
|
11
12
|
from xync_client.loader import PG_DSN
|
|
12
13
|
|
|
13
14
|
|
|
14
|
-
class
|
|
15
|
-
headers = {
|
|
15
|
+
class ExClient(BaseExClient):
|
|
16
|
+
headers = {
|
|
17
|
+
"accept-language": "ru,en;q=0.9",
|
|
18
|
+
"content-type": "application/json;charset=UTF-8",
|
|
19
|
+
"deviceid": "883e1394d8a2278418b6f02804df16c4",
|
|
20
|
+
}
|
|
16
21
|
|
|
17
22
|
async def curs(self) -> dict[str, str]:
|
|
18
23
|
curs = (await self._post("/v1/p2p/pub/currency/queryAllCoinAndFiat"))["data"]["fiatInfoRespList"]
|
|
@@ -23,14 +28,23 @@ class Client(BaseClient):
|
|
|
23
28
|
return {coin["coinCode"]: coin["coinCode"] for coin in coins}
|
|
24
29
|
|
|
25
30
|
async def pms(self) -> DictOfDicts: # {pm.exid: pm}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
for id_, cur in (await self.curs()).items():
|
|
32
|
+
pref = "../xync_client/BitGet/" if os.getcwd().split("/")[-1] == "tests" else ""
|
|
33
|
+
data = {"fiatCode": cur, "languageType": 6}
|
|
34
|
+
p = subprocess.Popen(
|
|
35
|
+
[
|
|
36
|
+
"node",
|
|
37
|
+
pref + "req.mjs",
|
|
38
|
+
"pub/currency/query-popular-paymethod",
|
|
39
|
+
json.dumps(data, separators=(",", ":")),
|
|
40
|
+
json.dumps(self.headers, separators=(",", ":")),
|
|
41
|
+
],
|
|
42
|
+
stdout=subprocess.PIPE,
|
|
43
|
+
)
|
|
44
|
+
out = p.stdout.read().decode()
|
|
45
|
+
pms: list[dict] = json.loads(out)
|
|
32
46
|
|
|
33
|
-
pmcurs = {
|
|
47
|
+
pmcurs = {pm["fiatCode"]: pm["paymethodInfo"] for pm in pms}
|
|
34
48
|
pp = {}
|
|
35
49
|
[
|
|
36
50
|
[pp.update({int(p["paymethodId"]): {"name": p["paymethodName"], "logo": p.get("iconUrl")}}) for p in ps]
|
|
@@ -76,7 +90,7 @@ class Client(BaseClient):
|
|
|
76
90
|
async def main():
|
|
77
91
|
_ = await init_db(PG_DSN, models, True)
|
|
78
92
|
bg = await Ex.get(name="BitGet")
|
|
79
|
-
cl =
|
|
93
|
+
cl = ExClient(bg)
|
|
80
94
|
# await cl.curs()
|
|
81
95
|
# await cl.coins()
|
|
82
96
|
# await cl.ads("BTC", "RUB", True, [1, 289, 375])
|
|
@@ -87,4 +101,5 @@ async def main():
|
|
|
87
101
|
await cl.close()
|
|
88
102
|
|
|
89
103
|
|
|
90
|
-
|
|
104
|
+
if __name__ == "__main__":
|
|
105
|
+
run(main())
|
|
@@ -2,8 +2,10 @@ from enum import IntEnum
|
|
|
2
2
|
from time import sleep
|
|
3
3
|
|
|
4
4
|
import pyotp
|
|
5
|
-
from
|
|
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
|
|
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 BybitP2P(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
|
-
def get_config(self):
|
|
101
|
-
resp = self._get("/fiat/p2p/config/initial", self.pub_header)
|
|
102
|
-
return resp["result"] # todo: tokens, pairs, ...
|
|
103
|
-
|
|
104
|
-
def get_currencies(self):
|
|
105
|
-
config = 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
|
|
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.
|
|
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 BybitP2P(Client): # Bybit client
|
|
|
142
109
|
return fiat
|
|
143
110
|
return list_methods[1]
|
|
144
111
|
|
|
145
|
-
|
|
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"] =
|
|
148
|
-
fiat["accountNo"] =
|
|
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.
|
|
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
|
-
|
|
157
|
-
|
|
158
|
-
|
|
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.
|
|
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 BybitP2P(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
|
|
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 BybitP2P(Client): # Bybit client
|
|
|
191
160
|
security_risk_token = data["result"]["securityRiskToken"]
|
|
192
161
|
return security_risk_token
|
|
193
162
|
|
|
194
|
-
def
|
|
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 BybitP2P(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.
|
|
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 BybitP2P(Client): # Bybit client
|
|
|
213
182
|
|
|
214
183
|
# создание объявлений
|
|
215
184
|
def post_create_ad(self, token: str):
|
|
216
|
-
|
|
217
|
-
assert
|
|
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 BybitP2P(Client): # Bybit client
|
|
|
230
199
|
return security_risk_token
|
|
231
200
|
|
|
232
201
|
def post_update_ad(self, token):
|
|
233
|
-
|
|
234
|
-
assert
|
|
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,58 @@
|
|
|
1
|
+
from enum import IntEnum
|
|
2
|
+
|
|
3
|
+
from xync_client.Abc.Base import ListOfDicts, MapOfIdsList
|
|
4
|
+
from xync_client.Abc.Ex import BaseExClient
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class AdsStatus(IntEnum):
|
|
8
|
+
REST = 0
|
|
9
|
+
WORKING = 1
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ExClient(BaseExClient): # Bybit client
|
|
13
|
+
host = "api2.bybit.com"
|
|
14
|
+
headers = {"cookie": ";"} # rewrite token for public methods
|
|
15
|
+
|
|
16
|
+
""" PUBLIC METHS """
|
|
17
|
+
|
|
18
|
+
async def get_ads(
|
|
19
|
+
self, coin: str, cur: str, sell: bool = False, amount: int = None, payment: list[str] = None
|
|
20
|
+
) -> list:
|
|
21
|
+
data = {
|
|
22
|
+
"userId": "",
|
|
23
|
+
"tokenId": coin,
|
|
24
|
+
"currencyId": cur,
|
|
25
|
+
"payment": payment or [],
|
|
26
|
+
"side": "0" if sell else "1",
|
|
27
|
+
"size": "10",
|
|
28
|
+
"page": "1",
|
|
29
|
+
"amount": str(amount) if amount else "",
|
|
30
|
+
"authMaker": False,
|
|
31
|
+
"canTrade": False,
|
|
32
|
+
}
|
|
33
|
+
ads = await self._post("/fiat/otc/item/online/", data)
|
|
34
|
+
return ads["result"]["items"]
|
|
35
|
+
|
|
36
|
+
async def get_config(self):
|
|
37
|
+
resp = await self._get("/fiat/p2p/config/initial")
|
|
38
|
+
return resp["result"] # todo: tokens, pairs, ...
|
|
39
|
+
|
|
40
|
+
async def curs(self):
|
|
41
|
+
config = await self.get_config()
|
|
42
|
+
return config["symbols"]
|
|
43
|
+
|
|
44
|
+
async def coins(self):
|
|
45
|
+
coins = await self._get("/spot/api/basic/symbol_list")
|
|
46
|
+
return coins
|
|
47
|
+
|
|
48
|
+
async def pms(self):
|
|
49
|
+
pms = await self._post("/fiat/otc/configuration/queryAllPaymentList/")
|
|
50
|
+
return pms
|
|
51
|
+
|
|
52
|
+
""" Private METHs"""
|
|
53
|
+
|
|
54
|
+
async def cur_pms_map(self) -> MapOfIdsList:
|
|
55
|
+
pass
|
|
56
|
+
|
|
57
|
+
async def ads(self, coin_exid: str, cur_exid: str, is_sell: bool, pm_exids: list[str | int] = None) -> ListOfDicts:
|
|
58
|
+
pass
|
xync_client-0.0.11.dev12/xync_client/Gate/pub.py → xync_client-0.0.11.dev15/xync_client/Gate/ex.py
RENAMED
|
@@ -12,7 +12,7 @@ from xync_client.Abc.Ex import BaseExClient
|
|
|
12
12
|
from xync_client.loader import PG_DSN
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
class
|
|
15
|
+
class ExClient(BaseExClient):
|
|
16
16
|
async def cur_pms_map(self) -> MapOfIdsList:
|
|
17
17
|
pass
|
|
18
18
|
|
|
@@ -60,10 +60,11 @@ class PublicClient(BaseExClient):
|
|
|
60
60
|
async def main():
|
|
61
61
|
_ = await init_db(PG_DSN, models, True)
|
|
62
62
|
bg = await Ex.get(name="Gate")
|
|
63
|
-
cl =
|
|
63
|
+
cl = ExClient(bg)
|
|
64
64
|
# await cl.curs()
|
|
65
65
|
# await cl.coins()
|
|
66
66
|
await cl.pms()
|
|
67
67
|
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
if __name__ == "__main__":
|
|
70
|
+
run(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"
|
|
@@ -5,11 +5,11 @@ from xync_schema import models
|
|
|
5
5
|
from xync_schema.models import Ex, Coin, Cur, Pm, Ad
|
|
6
6
|
from xync_schema.enums import PmType
|
|
7
7
|
|
|
8
|
-
from xync_client.Abc.Ex import
|
|
8
|
+
from xync_client.Abc.Ex import BaseExClient
|
|
9
9
|
from xync_client.loader import PG_DSN
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class
|
|
12
|
+
class ExClient(BaseExClient):
|
|
13
13
|
# 20: Get all pms
|
|
14
14
|
async def pms(self) -> dict[int, dict]:
|
|
15
15
|
dist = {
|
|
@@ -47,10 +47,12 @@ class Client(ExClient):
|
|
|
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"]
|
|
@@ -64,10 +66,11 @@ class Client(ExClient):
|
|
|
64
66
|
async def main():
|
|
65
67
|
_ = await init_db(PG_DSN, models, True)
|
|
66
68
|
ex = await Ex.get(name="Htx")
|
|
67
|
-
cl =
|
|
69
|
+
cl = ExClient(ex)
|
|
68
70
|
await cl.set_pmcurexs()
|
|
69
71
|
await cl.set_coinexs()
|
|
70
72
|
await cl.close()
|
|
71
73
|
|
|
72
74
|
|
|
73
|
-
|
|
75
|
+
if __name__ == "__main__":
|
|
76
|
+
run(main())
|
|
@@ -1,38 +1,31 @@
|
|
|
1
|
-
from enum import StrEnum
|
|
1
|
+
from enum import StrEnum
|
|
2
2
|
from typing import Literal
|
|
3
3
|
|
|
4
|
-
from
|
|
4
|
+
from xync_client.TgWallet.auth import AuthClient
|
|
5
5
|
from xync_schema.models import User, Cur, Order, Coin, OrderStatus, Pmex
|
|
6
6
|
from xync_schema.pydantic import FiatNew
|
|
7
7
|
|
|
8
8
|
from xync_client.Abc.Agent import BaseAgentClient
|
|
9
|
-
from xync_client.TgWallet.pyro import PyroClient
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
class Exceptions(StrEnum):
|
|
13
12
|
PM_KYC = "OFFER_FIAT_COUNTRY_NOT_SUPPORTED_BY_USER_KYC_COUNTRY"
|
|
14
13
|
|
|
15
14
|
|
|
16
|
-
class Status(IntEnum):
|
|
17
|
-
|
|
15
|
+
# class Status(IntEnum):
|
|
16
|
+
# ALL_ACTIVE = OrderStatus.active
|
|
18
17
|
|
|
19
18
|
|
|
20
|
-
class AgentClient(BaseAgentClient):
|
|
19
|
+
class AgentClient(BaseAgentClient, AuthClient):
|
|
21
20
|
async def order_request(self, ad_id: int, amount: float) -> Order:
|
|
22
21
|
pass
|
|
23
22
|
|
|
24
|
-
async def _get_auth_hdrs(self) -> dict[str, str]:
|
|
25
|
-
pyro = PyroClient(self.agent)
|
|
26
|
-
init_data = await pyro.get_init_data()
|
|
27
|
-
tokens = HttpClient("walletbot.me")._post("/api/v1/users/auth/", init_data)
|
|
28
|
-
return {"Wallet-Authorization": tokens["jwt"], "Authorization": "Bearer " + tokens["value"]}
|
|
29
|
-
|
|
30
23
|
async def get_orders(
|
|
31
24
|
self, stauts: OrderStatus = OrderStatus.active, coin: Coin = None, cur: Cur = None, is_sell: bool = None
|
|
32
25
|
) -> list[Order]:
|
|
33
26
|
orders = await self._post(
|
|
34
27
|
"/p2p/public-api/v2/offer/order/history/get-by-user-id",
|
|
35
|
-
{"offset": 0, "limit": 100, "filter": {"status":
|
|
28
|
+
{"offset": 0, "limit": 100, "filter": {"status": "ALL_ACTIVE"}}, # "limit": 20
|
|
36
29
|
)
|
|
37
30
|
return orders
|
|
38
31
|
|
|
@@ -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,10 +1,11 @@
|
|
|
1
|
-
from xync_client.
|
|
1
|
+
from xync_client.TgWallet.auth import AuthClient
|
|
2
|
+
|
|
2
3
|
from xync_schema.models import Pm
|
|
3
4
|
|
|
4
5
|
from xync_client.Abc.Ex import BaseExClient
|
|
5
6
|
|
|
6
7
|
|
|
7
|
-
class ExClient(BaseExClient,
|
|
8
|
+
class ExClient(BaseExClient, AuthClient):
|
|
8
9
|
async def curs(self) -> dict[str, str]:
|
|
9
10
|
coins_curs = await self._post("/p2p/public-api/v2/currency/all-supported")
|
|
10
11
|
return {c["code"]: c["code"] for c in coins_curs["data"]["fiat"]}
|
|
File without changes
|
|
@@ -4,8 +4,12 @@
|
|
|
4
4
|
README.md
|
|
5
5
|
makefile
|
|
6
6
|
pyproject.toml
|
|
7
|
+
tests/TestEx.py
|
|
7
8
|
tests/__init__.py
|
|
8
|
-
tests/
|
|
9
|
+
tests/_test_ex.py
|
|
10
|
+
tests/Abc/AgentTest.py
|
|
11
|
+
tests/Abc/BaseTest.py
|
|
12
|
+
tests/Abc/OrderTest.py
|
|
9
13
|
tests/Binance/test_binance.py
|
|
10
14
|
tests/Bybit/test_bybit.py
|
|
11
15
|
tests/Bybit/test_bybit_p2p.py
|
|
@@ -23,10 +27,6 @@ xync_client/Abc/Auth.py
|
|
|
23
27
|
xync_client/Abc/Base.py
|
|
24
28
|
xync_client/Abc/Ex.py
|
|
25
29
|
xync_client/Abc/Order.py
|
|
26
|
-
xync_client/AbcTest/AgentTest.py
|
|
27
|
-
xync_client/AbcTest/BaseTest.py
|
|
28
|
-
xync_client/AbcTest/ExTest.py
|
|
29
|
-
xync_client/AbcTest/OrderTest.py
|
|
30
30
|
xync_client/Binance/__init__.py
|
|
31
31
|
xync_client/Binance/binance_async.py
|
|
32
32
|
xync_client/Binance/earn_api.py
|
|
@@ -34,6 +34,7 @@ xync_client/Binance/ex.py
|
|
|
34
34
|
xync_client/Binance/exceptions.py
|
|
35
35
|
xync_client/Binance/sapi.py
|
|
36
36
|
xync_client/Binance/web_c2c.py
|
|
37
|
+
xync_client/BingX/__init__.py
|
|
37
38
|
xync_client/BingX/base.py
|
|
38
39
|
xync_client/BingX/ex.py
|
|
39
40
|
xync_client/BingX/req.mjs
|
|
@@ -43,11 +44,12 @@ xync_client/BitGet/__init__.py
|
|
|
43
44
|
xync_client/BitGet/agent.py
|
|
44
45
|
xync_client/BitGet/ex.py
|
|
45
46
|
xync_client/BitGet/req.mjs
|
|
47
|
+
xync_client/Bybit/agent.py
|
|
46
48
|
xync_client/Bybit/ex.py
|
|
47
49
|
xync_client/Bybit/web_earn.py
|
|
48
50
|
xync_client/Bybit/web_p2p.py
|
|
51
|
+
xync_client/Gate/ex.py
|
|
49
52
|
xync_client/Gate/premarket.py
|
|
50
|
-
xync_client/Gate/pub.py
|
|
51
53
|
xync_client/Htx/agent.py
|
|
52
54
|
xync_client/Htx/earn.py
|
|
53
55
|
xync_client/Htx/ex.py
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
|
|
3
|
-
from xync_client.Abc.Base import BaseClient
|
|
4
|
-
from xync_client.Abc.BaseTest import BaseTest
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class AgentTest(BaseTest):
|
|
8
|
-
@pytest.fixture(scope="class", autouse=True)
|
|
9
|
-
async def cl(self) -> BaseClient:
|
|
10
|
-
agent = (await self.exq).agents.filter(auth__not_isnull=True).first()
|
|
11
|
-
acl = BaseClient(agent)
|
|
12
|
-
yield acl
|
|
13
|
-
await acl.close()
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
from typing import TypeGuard
|
|
3
|
-
from src.loader import PG_DSN
|
|
4
|
-
from tortoise.backends.asyncpg import AsyncpgDBClient
|
|
5
|
-
from x_model import init_db
|
|
6
|
-
from xync_schema import models
|
|
7
|
-
from xync_schema.models import Ex
|
|
8
|
-
|
|
9
|
-
from xync_client.Abc.Base import DictOfDicts, ListOfDicts, FlatDict, MapOfIdsList, BaseClient
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class BaseTest:
|
|
13
|
-
def __init__(self, ex_name: str):
|
|
14
|
-
self.exq = Ex.get(name=ex_name)
|
|
15
|
-
|
|
16
|
-
@pytest.fixture(scope="class", autouse=True)
|
|
17
|
-
async def cn(self) -> AsyncpgDBClient:
|
|
18
|
-
cn: AsyncpgDBClient = await init_db(PG_DSN, models, True)
|
|
19
|
-
yield cn
|
|
20
|
-
await cn.close()
|
|
21
|
-
|
|
22
|
-
@pytest.fixture(scope="class", autouse=True)
|
|
23
|
-
async def cl(self) -> BaseClient:
|
|
24
|
-
bcl = BaseClient(await self.exq)
|
|
25
|
-
yield bcl
|
|
26
|
-
await bcl.close()
|
|
27
|
-
|
|
28
|
-
@staticmethod
|
|
29
|
-
def is_dict_of_dicts(dct: DictOfDicts) -> TypeGuard[DictOfDicts]:
|
|
30
|
-
return all(isinstance(k, int | str) and isinstance(v, dict) for k, v in dct.items())
|
|
31
|
-
|
|
32
|
-
@staticmethod
|
|
33
|
-
def is_list_of_dicts(lst: ListOfDicts) -> TypeGuard[ListOfDicts]:
|
|
34
|
-
return all(isinstance(el, dict) for el in lst)
|
|
35
|
-
|
|
36
|
-
@staticmethod
|
|
37
|
-
def is_flat_dict(dct: FlatDict) -> TypeGuard[FlatDict]:
|
|
38
|
-
return all(isinstance(k, int | str) and isinstance(v, str) for k, v in dct.items())
|
|
39
|
-
|
|
40
|
-
@staticmethod
|
|
41
|
-
def is_map_of_ids(dct: MapOfIdsList) -> TypeGuard[MapOfIdsList]:
|
|
42
|
-
return all(isinstance(k, int | str) and isinstance(v, str) for k, v in dct.items())
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
|
|
3
|
-
from xync_client.Abc.Ex import BaseExClient
|
|
4
|
-
from xync_client.Abc.BaseTest import BaseTest
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class ExTest(BaseTest):
|
|
8
|
-
@pytest.fixture(scope="class", autouse=True)
|
|
9
|
-
async def cl(self) -> BaseExClient:
|
|
10
|
-
ecl = BaseExClient(await self.exq)
|
|
11
|
-
yield ecl
|
|
12
|
-
await ecl.close()
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import requests
|
|
2
|
-
|
|
3
|
-
headers = {
|
|
4
|
-
"accept": "application/json, text/plain, */*",
|
|
5
|
-
"accept-language": "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7",
|
|
6
|
-
"app_version": "9.0.0",
|
|
7
|
-
"appid": "30004",
|
|
8
|
-
"appsiteid": "0",
|
|
9
|
-
"channel": "official",
|
|
10
|
-
"device_brand": "Linux_Chrome_131.0.0.0",
|
|
11
|
-
"device_id": "64a8c630-acc2-11ef-aa5e-9f6ee3baa1a5",
|
|
12
|
-
"lang": "ru-RU",
|
|
13
|
-
"mainappid": "10009",
|
|
14
|
-
"origin": "https://bingx.paycat.com",
|
|
15
|
-
"platformid": "30",
|
|
16
|
-
"priority": "u=1, i",
|
|
17
|
-
"referer": "https://bingx.paycat.com/",
|
|
18
|
-
"reg_channel": "official",
|
|
19
|
-
"sec-ch-ua": '"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
|
|
20
|
-
"sec-ch-ua-mobile": "?0",
|
|
21
|
-
"sec-ch-ua-platform": '"Linux"',
|
|
22
|
-
"sec-fetch-dest": "empty",
|
|
23
|
-
"sec-fetch-mode": "cors",
|
|
24
|
-
"sec-fetch-site": "cross-site",
|
|
25
|
-
"sign": "C2F082935161A29256CDD98F2E33FBE3C9B2C0864A6FBCB1881013CBE6272AC8",
|
|
26
|
-
"timestamp": "1734637010958",
|
|
27
|
-
"timezone": "3",
|
|
28
|
-
"traceid": "3e38538d69fb43c9a009ea1fc00a9b8f",
|
|
29
|
-
"user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
|
|
30
|
-
"x-requested-with": "XMLHttpRequest",
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
params = {
|
|
34
|
-
"fiat": "RUB",
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
response = requests.get("https://api-app.we-api.com/api/c2c/v1/advert/payment/list", params=params, headers=headers)
|
|
38
|
-
|
|
39
|
-
print(i for i in response.json()["data"]["paymentMethodList"])
|
|
@@ -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"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{xync_client-0.0.11.dev12/xync_client/AbcTest → xync_client-0.0.11.dev15/tests/Abc}/OrderTest.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{xync_client-0.0.11.dev12/xync_client → xync_client-0.0.11.dev15/xync_client/BitGet}/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{xync_client-0.0.11.dev12 → xync_client-0.0.11.dev15}/xync_client.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|