xync-client 0.0.11.dev0__tar.gz → 0.0.11.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.
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/.gitignore +2 -1
- {xync_client-0.0.11.dev0/xync_client.egg-info → xync_client-0.0.11.dev4}/PKG-INFO +1 -1
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/tests/Binance/test_binance.py +3 -5
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/tests/test_ex.py +5 -6
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/Abc/Agent.py +3 -43
- xync_client-0.0.11.dev4/xync_client/Abc/Auth.py +9 -0
- xync_client-0.0.11.dev4/xync_client/Abc/Base.py +12 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/Abc/Ex.py +16 -21
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/Abc/Order.py +17 -8
- xync_client-0.0.11.dev4/xync_client/Abc/Test.py +21 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/Binance/ex.py +11 -16
- xync_client-0.0.11.dev4/xync_client/BingX/ex.py +52 -0
- xync_client-0.0.11.dev4/xync_client/BingX/test/main.py +22 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/BitGet/agent.py +3 -3
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/BitGet/ex.py +14 -4
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/Gate/premarket.py +1 -1
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/Gate/pub.py +7 -3
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/KuCoin/pub.py +7 -3
- xync_client-0.0.11.dev0/xync_client/Okx/pub.py → xync_client-0.0.11.dev4/xync_client/Okx/ex.py +9 -8
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/TgWallet/agent.py +2 -5
- xync_client-0.0.11.dev4/xync_client/TgWallet/auth.py +39 -0
- xync_client-0.0.11.dev4/xync_client/TgWallet/ex.py +40 -0
- xync_client-0.0.11.dev4/xync_client/TgWallet/order.py +77 -0
- xync_client-0.0.11.dev4/xync_client/__init__.py +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4/xync_client.egg-info}/PKG-INFO +1 -1
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client.egg-info/SOURCES.txt +8 -1
- xync_client-0.0.11.dev0/xync_client/TgWallet/ex.py +0 -78
- xync_client-0.0.11.dev0/xync_client/TgWallet/order.py +0 -215
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/.env.sample +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/.pre-commit-config.yaml +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/README.md +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/makefile +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/pyproject.toml +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/setup.cfg +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/tests/Bybit/test_bybit.py +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/tests/Bybit/test_bybit_p2p.py +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/tests/Gate/test_gate.py +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/tests/Htx/test_htx_p2p.py +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/tests/__init__.py +0 -0
- {xync_client-0.0.11.dev0/xync_client/BitGet → xync_client-0.0.11.dev4/xync_client/Binance}/__init__.py +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/Binance/binance_async.py +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/Binance/earn_api.py +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/Binance/exceptions.py +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/Binance/sapi.py +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/Binance/web_c2c.py +0 -0
- {xync_client-0.0.11.dev0/xync_client → xync_client-0.0.11.dev4/xync_client/BitGet}/__init__.py +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/BitGet/req.mjs +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/Bybit/ex.py +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/Bybit/web_earn.py +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/Bybit/web_p2p.py +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/Htx/agent.py +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/Htx/earn.py +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/Htx/ex.py +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/KuCoin/web.py +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/TgWallet/pyro.py +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/TgWallet/web.py +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client/loader.py +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client.egg-info/dependency_links.txt +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client.egg-info/requires.txt +0 -0
- {xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client.egg-info/top_level.txt +0 -0
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
from x_model import init_db
|
|
2
|
-
from xync_client.loader import
|
|
2
|
+
from xync_client.loader import PG_DSN
|
|
3
3
|
from xync_schema import models
|
|
4
4
|
from xync_schema.models import Ex
|
|
5
5
|
|
|
6
|
-
from xync_client.Binance.ex import Client
|
|
7
|
-
|
|
8
6
|
|
|
9
7
|
async def test_cur_filter():
|
|
10
|
-
_ = await init_db(
|
|
8
|
+
_ = await init_db(PG_DSN, models, True)
|
|
11
9
|
ex = await Ex.get(name="Binance")
|
|
12
|
-
bn =
|
|
10
|
+
bn = await ex.client()
|
|
13
11
|
resp = await bn.cur_pms_map()
|
|
14
12
|
assert len(resp[0]) and len(resp[1]), "No data"
|
|
@@ -7,7 +7,6 @@ from x_model import init_db
|
|
|
7
7
|
from xync_schema import models
|
|
8
8
|
from xync_schema.models import Agent, ExAction, TestEx
|
|
9
9
|
|
|
10
|
-
from xync_client.TgWallet.ex import PublicClient
|
|
11
10
|
from xync_client.loader import PG_DSN
|
|
12
11
|
|
|
13
12
|
|
|
@@ -36,26 +35,26 @@ class TestWallet:
|
|
|
36
35
|
# 20 - all_pms
|
|
37
36
|
async def test_all_pms(self, cl):
|
|
38
37
|
pms = await cl.pms()
|
|
39
|
-
|
|
38
|
+
pms and cl.is_pms(pms)
|
|
40
39
|
test, _ = await TestEx.update_or_create({"ok": bool(pms)}, ex=cl.ex, action=ExAction.pms)
|
|
41
40
|
assert test.ok, "No pms"
|
|
42
41
|
|
|
43
42
|
# 21 - all_curs
|
|
44
43
|
async def test_all_curs(self, cl):
|
|
45
44
|
curs = await cl.curs()
|
|
46
|
-
test, _ = await TestEx.update_or_create({"ok": bool(curs)},
|
|
45
|
+
test, _ = await TestEx.update_or_create({"ok": bool(curs)}, ex=cl.ex, action=ExAction.curs)
|
|
47
46
|
assert test.ok, "No curs"
|
|
48
47
|
|
|
49
48
|
# 22 - all_pms
|
|
50
49
|
async def test_cur_pms_map(self, cl):
|
|
51
50
|
pms = await cl.cur_pms_map()
|
|
52
|
-
test, _ = await TestEx.update_or_create({"ok": bool(pms)},
|
|
51
|
+
test, _ = await TestEx.update_or_create({"ok": bool(pms)}, ex=cl.ex, action=ExAction.pms)
|
|
53
52
|
assert test.ok, "No pms"
|
|
54
53
|
|
|
55
54
|
# 23 - all_coins
|
|
56
55
|
async def test_all_coins(self, cl):
|
|
57
56
|
coins = await cl.coins()
|
|
58
|
-
test, _ = await TestEx.update_or_create({"ok": bool(coins)},
|
|
57
|
+
test, _ = await TestEx.update_or_create({"ok": bool(coins)}, ex=cl.ex, action=ExAction.coins)
|
|
59
58
|
assert test.ok, "No coins"
|
|
60
59
|
|
|
61
60
|
# 24 - all_ads
|
|
@@ -65,4 +64,4 @@ class TestWallet:
|
|
|
65
64
|
for tt in True, False:
|
|
66
65
|
ads = await cl.ads(coin, cur, tt)
|
|
67
66
|
assert len(ads), "No data"
|
|
68
|
-
await TestEx.update_or_create({"ok": bool(ads)},
|
|
67
|
+
await TestEx.update_or_create({"ok": bool(ads)}, ex=cl.ex, action=ExAction.ads)
|
|
@@ -1,33 +1,12 @@
|
|
|
1
|
-
import logging
|
|
2
1
|
from abc import abstractmethod
|
|
3
2
|
|
|
4
|
-
from
|
|
5
|
-
from aiohttp.http_exceptions import HttpProcessingError
|
|
6
|
-
from x_client.aiohttp import Client as HttpClient
|
|
3
|
+
from xync_client.Abc.Auth import BaseAuthClient
|
|
7
4
|
from xync_schema.enums import PmType
|
|
8
|
-
from xync_schema.models import
|
|
5
|
+
from xync_schema.models import OrderStatus, Coin, Cur, Order, Pm, Ad, AdStatus, Fiat
|
|
9
6
|
from xync_schema.pydantic import FiatNew
|
|
10
7
|
|
|
11
8
|
|
|
12
|
-
class
|
|
13
|
-
def __init__(self, agent: Agent):
|
|
14
|
-
self.agent: Agent = agent
|
|
15
|
-
assert isinstance(agent.ex, Ex), "`ex` should be fetched in `agent`"
|
|
16
|
-
assert agent.ex.host_p2p, "`ex.host_p2p` shouldn't be empty"
|
|
17
|
-
self.meth = {
|
|
18
|
-
"GET": self._get,
|
|
19
|
-
"POST": self._post,
|
|
20
|
-
}
|
|
21
|
-
super().__init__(agent.ex.host_p2p)
|
|
22
|
-
|
|
23
|
-
# Login: returns auth headers dict
|
|
24
|
-
async def _get_auth_hdrs(self) -> dict[str, str]:
|
|
25
|
-
return self.agent.auth
|
|
26
|
-
|
|
27
|
-
async def login(self) -> None:
|
|
28
|
-
auth_hdrs: dict[str, str] = await self._get_auth_hdrs()
|
|
29
|
-
self.session.headers.update(auth_hdrs)
|
|
30
|
-
|
|
9
|
+
class BaseAgentClient(BaseAuthClient):
|
|
31
10
|
# 0: Получшение ордеров в статусе status, по монете coin, в валюте coin, в направлении is_sell: bool
|
|
32
11
|
@abstractmethod
|
|
33
12
|
async def get_orders(
|
|
@@ -120,22 +99,3 @@ class Client(HttpClient):
|
|
|
120
99
|
# 38: Поставить отзыв юзеру
|
|
121
100
|
@abstractmethod
|
|
122
101
|
async def rate_user(self, positive: bool) -> bool: ...
|
|
123
|
-
|
|
124
|
-
async def _proc(self, resp: ClientResponse, data: dict = None) -> dict | str:
|
|
125
|
-
try:
|
|
126
|
-
return await super()._proc(resp)
|
|
127
|
-
except HttpProcessingError as e:
|
|
128
|
-
if e.code == 401:
|
|
129
|
-
logging.warning(e)
|
|
130
|
-
await self.login()
|
|
131
|
-
res = await self.meth[resp.method](resp.url.path, data)
|
|
132
|
-
return res
|
|
133
|
-
|
|
134
|
-
@staticmethod
|
|
135
|
-
async def payment_methods(*methods_list):
|
|
136
|
-
payment_list = []
|
|
137
|
-
for method in methods_list:
|
|
138
|
-
method_cleared = method.lower().replace(" ", "").replace("-", "").replace("(", "").replace(")", "")
|
|
139
|
-
if method_cleared not in payment_list:
|
|
140
|
-
payment_list.append(method_cleared)
|
|
141
|
-
return payment_list
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from x_client.aiohttp import Client
|
|
2
|
+
from xync_schema.models import Ex
|
|
3
|
+
|
|
4
|
+
DictOfDicts = dict[int | str, dict]
|
|
5
|
+
ListOfDicts = list[dict]
|
|
6
|
+
FlatDict = dict[int | str, str]
|
|
7
|
+
MapOfIdsList = dict[int | str, list[int | str]]
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class BaseClient(Client):
|
|
11
|
+
def __init__(self, ex: Ex):
|
|
12
|
+
super().__init__(ex.host_p2p)
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import re
|
|
3
3
|
from abc import abstractmethod
|
|
4
|
-
from typing import TypeGuard
|
|
5
4
|
|
|
6
|
-
from
|
|
5
|
+
from xync_client.Abc.Base import BaseClient, DictOfDicts, FlatDict, ListOfDicts, MapOfIdsList
|
|
7
6
|
from xync_schema.models import Ex, Coin, Cur, Pm, Pmex, Curex, Pmcur, Pmcurex, Coinex
|
|
8
7
|
|
|
9
8
|
|
|
10
|
-
class
|
|
9
|
+
class BaseExClient(BaseClient):
|
|
11
10
|
ex: Ex
|
|
12
11
|
pm_map: dict[str, str] = {
|
|
13
12
|
"Юmoney": "YooMoney",
|
|
@@ -23,51 +22,47 @@ class ExClient(Client):
|
|
|
23
22
|
|
|
24
23
|
def __init__(self, ex: Ex):
|
|
25
24
|
self.ex = ex
|
|
26
|
-
self.
|
|
27
|
-
super().__init__(ex
|
|
28
|
-
|
|
29
|
-
@staticmethod
|
|
30
|
-
def is_pms(val: dict[int | str, dict]) -> TypeGuard[dict[int | str, dict]]:
|
|
31
|
-
return all(isinstance(k, int | str) and isinstance(v, dict) for k, v in val.items())
|
|
25
|
+
self.acronyms: dict[str, str] = {} # for pm norm
|
|
26
|
+
super().__init__(ex)
|
|
32
27
|
|
|
33
28
|
# 20: Список всех платежных методов на бирже
|
|
34
29
|
@abstractmethod
|
|
35
|
-
async def pms(self) ->
|
|
30
|
+
async def pms(self) -> DictOfDicts: # {pm.exid: pm}
|
|
36
31
|
...
|
|
37
32
|
|
|
38
33
|
# 21: Список поддерживаемых валют
|
|
39
34
|
@abstractmethod
|
|
40
|
-
async def curs(self) ->
|
|
35
|
+
async def curs(self) -> FlatDict: # {cur.exid: cur.ticker}
|
|
41
36
|
...
|
|
42
37
|
|
|
43
38
|
# 22: Список платежных методов по каждой валюте
|
|
44
39
|
@abstractmethod
|
|
45
|
-
async def cur_pms_map(self) ->
|
|
40
|
+
async def cur_pms_map(self) -> MapOfIdsList: # {cur.exid: [pm.exid]}
|
|
46
41
|
...
|
|
47
42
|
|
|
48
43
|
# 23: Список торгуемых монет (с ограничениям по валютам, если есть)
|
|
49
44
|
@abstractmethod
|
|
50
|
-
async def coins(self) ->
|
|
45
|
+
async def coins(self) -> FlatDict: # {coin.exid: coin.ticker}
|
|
51
46
|
...
|
|
52
47
|
|
|
53
48
|
# 24: Список объяв по (buy/sell, cur, coin, pm)
|
|
54
49
|
@abstractmethod
|
|
55
50
|
async def ads(
|
|
56
51
|
self, coin_exid: str, cur_exid: str, is_sell: bool, pm_exids: list[str | int] = None
|
|
57
|
-
) ->
|
|
52
|
+
) -> ListOfDicts: # {ad.id: ad}
|
|
58
53
|
...
|
|
59
54
|
|
|
60
|
-
def _pmnorm(self, s: str
|
|
55
|
+
def _pmnorm(self, s: str) -> str:
|
|
61
56
|
def get_and_remove_acro(title: str) -> str:
|
|
62
57
|
acr = "".join(word[0] for word in title.split(" ") if len(word) > 1 and word.istitle())
|
|
63
58
|
if len(acr) > 2:
|
|
64
59
|
title = title.replace(acr, "", 1)
|
|
65
|
-
self.
|
|
60
|
+
self.acronyms[acr] = title # заполняем словарь аббревиатур
|
|
66
61
|
return title
|
|
67
62
|
|
|
68
63
|
def find_and_replace_only_acro(title: str) -> str:
|
|
69
|
-
if " " not in title and title.isupper() and title in self.
|
|
70
|
-
title = self.
|
|
64
|
+
if " " not in title and title.isupper() and title in self.acronyms:
|
|
65
|
+
title = self.acronyms[title]
|
|
71
66
|
return title
|
|
72
67
|
|
|
73
68
|
def remove(rms: str | list[str], st: str, regexp: bool = False) -> str:
|
|
@@ -120,17 +115,17 @@ class ExClient(Client):
|
|
|
120
115
|
async def set_pmcurexs(self):
|
|
121
116
|
# Pms
|
|
122
117
|
pmsd = {k: v for k, v in sorted((await self.pms()).items(), key=lambda x: x[1]["name"])} # sort by name
|
|
123
|
-
pms: dict[int | str, Pm] = {}
|
|
118
|
+
pms: dict[int | str, Pm] = dict({})
|
|
124
119
|
prev = 0, "", "" # id, normd-name, orig-name
|
|
125
120
|
for k, pm in pmsd.items():
|
|
126
121
|
norm = self._pmnorm(pm["name"])
|
|
127
122
|
if prev[1:] == (norm, pm["name"]):
|
|
128
|
-
logging.warning(f"Pm: '{pm['name']}' duplicated with ids {prev[0]}:{k} on {self.ex.name}")
|
|
123
|
+
logging.warning(f"Pm: '{pm['name']}' duplicated with ids {prev[0]}: {k} on {self.ex.name}")
|
|
129
124
|
pm_ = pms.get(prev[0], (await Pm.get_or_none(name=prev[2])) or await Pm.get_or_none(identifier=prev[1]))
|
|
130
125
|
await Pmex.update_or_create({"pm": pm_}, ex=self.ex, exid=k, name=pm["name"])
|
|
131
126
|
elif prev[1] == norm:
|
|
132
127
|
logging.error(
|
|
133
|
-
f"Pm: '{pm['name']}'
|
|
128
|
+
f"Pm: '{pm['name']}' & '{prev[2]}' overnormd as '{norm}' with ids {prev[0]}: {k} on {self.ex.name}"
|
|
134
129
|
)
|
|
135
130
|
await Pmex.update_or_create(
|
|
136
131
|
{"pm": pms.get(prev[0], await Pm.get(name=prev[2]))}, ex=self.ex, exid=k, name=pm["name"]
|
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
from abc import abstractmethod
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
from xync_schema.models import Order
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
from xync_client.Abc.Auth import BaseAuthClient
|
|
4
|
+
from xync_schema.models import Order, Agent
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class BaseOrderClient(BaseAuthClient):
|
|
8
|
+
order: Order
|
|
9
|
+
is_sell: bool
|
|
10
|
+
im_maker: bool
|
|
11
|
+
im_seller: bool
|
|
12
|
+
|
|
13
|
+
def __init__(self, agent: Agent, order: Order):
|
|
14
|
+
self.order = order
|
|
15
|
+
self.is_sell = order.ad.direction.sell
|
|
16
|
+
# self.im_maker = order.ad.agent_id == agent.id
|
|
17
|
+
self.im_maker = order.taker_id != agent.id
|
|
18
|
+
self.im_seller = self.is_sell and self.im_maker
|
|
19
|
+
super().__init__(agent)
|
|
11
20
|
|
|
12
21
|
# 2: [T] Отмена запроса на сделку
|
|
13
22
|
@abstractmethod
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from typing import TypeGuard
|
|
2
|
+
|
|
3
|
+
from xync_client.Abc.Base import DictOfDicts, ListOfDicts, FlatDict, MapOfIdsList
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BaseTest:
|
|
7
|
+
@staticmethod
|
|
8
|
+
def is_dod(dct: DictOfDicts) -> TypeGuard[DictOfDicts]:
|
|
9
|
+
return all(isinstance(k, int | str) and isinstance(v, dict) for k, v in dct.items())
|
|
10
|
+
|
|
11
|
+
@staticmethod
|
|
12
|
+
def is_lod(lst: ListOfDicts) -> TypeGuard[ListOfDicts]:
|
|
13
|
+
return all(isinstance(el, dict) for el in lst)
|
|
14
|
+
|
|
15
|
+
@staticmethod
|
|
16
|
+
def is_fd(dct: FlatDict) -> TypeGuard[FlatDict]:
|
|
17
|
+
return all(isinstance(k, int | str) and isinstance(v, str) for k, v in dct.items())
|
|
18
|
+
|
|
19
|
+
@staticmethod
|
|
20
|
+
def is_moil(dct: MapOfIdsList) -> TypeGuard[MapOfIdsList]:
|
|
21
|
+
return all(isinstance(k, int | str) and isinstance(v, str) for k, v in dct.items())
|
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
from asyncio import run
|
|
2
|
-
|
|
3
|
-
from x_model import init_db
|
|
4
1
|
from xync_schema.enums import PmType
|
|
5
2
|
|
|
6
|
-
from xync_client.Abc.Ex import
|
|
3
|
+
from xync_client.Abc.Ex import BaseClient
|
|
7
4
|
from xync_client.Binance.sapi import Sapi
|
|
8
|
-
from xync_client.loader import PG_DSN, BKEY, BSEC
|
|
9
|
-
from xync_schema import models
|
|
10
5
|
from xync_schema.models import Ex
|
|
11
6
|
|
|
12
7
|
|
|
13
|
-
class Client(
|
|
8
|
+
class Client(BaseClient):
|
|
14
9
|
def __init__(self, ex: Ex, bkeys):
|
|
15
10
|
self.sapi = Sapi(*bkeys)
|
|
16
11
|
super().__init__(ex)
|
|
@@ -74,12 +69,12 @@ class Client(ExClient):
|
|
|
74
69
|
# }
|
|
75
70
|
|
|
76
71
|
|
|
77
|
-
async def main():
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
run(main())
|
|
72
|
+
# async def main():
|
|
73
|
+
# _ = await init_db(PG_DSN, models, True)
|
|
74
|
+
# ex = await Ex.get(name="Binance")
|
|
75
|
+
# cl = Client(ex, (BKEY, BSEC))
|
|
76
|
+
# await cl.set_pmcurexs()
|
|
77
|
+
# await cl.close()
|
|
78
|
+
#
|
|
79
|
+
#
|
|
80
|
+
# run(main())
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from asyncio import run
|
|
2
|
+
|
|
3
|
+
from x_model import init_db
|
|
4
|
+
from xync_schema import models
|
|
5
|
+
from xync_schema.models import Ex
|
|
6
|
+
|
|
7
|
+
from xync_client.Abc.Ex import BaseExClient
|
|
8
|
+
from xync_client.loader import PG_DSN
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Client(BaseExClient):
|
|
12
|
+
# 20: order_request
|
|
13
|
+
async def pms(self):
|
|
14
|
+
# for cur in self.curs():
|
|
15
|
+
for cur in ["RUB", "THB", "PHP"]: # todo: temp hardcode curs
|
|
16
|
+
params = {
|
|
17
|
+
"coinName": "USDT",
|
|
18
|
+
"tradeCoinName": cur,
|
|
19
|
+
"type": "1",
|
|
20
|
+
"amount": "500",
|
|
21
|
+
}
|
|
22
|
+
pms = await self._get("/api/fiat/v1/rapid-buy-integration", params=params)
|
|
23
|
+
|
|
24
|
+
return [pm.get("paymentMethod")["name"] for pm in pms["data"]["matchOptimalAdvertListVo"]["optimals"]]
|
|
25
|
+
|
|
26
|
+
# 21: order_request_ask
|
|
27
|
+
async def curs(self):
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
# 22: cur_pms_map
|
|
31
|
+
async def cur_pms_map(self):
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
# 23: coins
|
|
35
|
+
async def coins(self):
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
# 24: ads
|
|
39
|
+
async def ads(self, coin_exid: str, cur_exid: str, is_sell: bool, pm_exids: list[str | int] = None):
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
async def main():
|
|
44
|
+
_ = await init_db(PG_DSN, models, True)
|
|
45
|
+
bg = await Ex.get(name="BingX")
|
|
46
|
+
cl = Client(bg)
|
|
47
|
+
await cl.curs()
|
|
48
|
+
await cl.pms()
|
|
49
|
+
await cl.close()
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
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"]])
|
|
@@ -7,11 +7,11 @@ from xync_schema.enums import AdStatus, PmType, OrderStatus
|
|
|
7
7
|
from xync_schema.models import User, Pm, Coin, Cur, Ad, Fiat, Order, Agent
|
|
8
8
|
from xync_schema.pydantic import FiatNew
|
|
9
9
|
|
|
10
|
-
from xync_client.Abc.Agent import
|
|
10
|
+
from xync_client.Abc.Agent import BaseAgentClient
|
|
11
11
|
from xync_client.loader import PG_DSN
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
class Client(
|
|
14
|
+
class Client(BaseAgentClient):
|
|
15
15
|
headers = {"accept-language": "ru,en;q=0.9"}
|
|
16
16
|
|
|
17
17
|
def __init__(self, agent: Agent):
|
|
@@ -106,7 +106,7 @@ async def main():
|
|
|
106
106
|
_ = await init_db(PG_DSN, models, True)
|
|
107
107
|
agent = await Agent.get(ex__name="BitGet").prefetch_related("ex")
|
|
108
108
|
cl = Client(agent)
|
|
109
|
-
|
|
109
|
+
await cl.my_fiats()
|
|
110
110
|
await cl.close()
|
|
111
111
|
|
|
112
112
|
|
|
@@ -1,14 +1,18 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import subprocess
|
|
1
3
|
from asyncio import run
|
|
2
4
|
|
|
3
5
|
from x_model import init_db
|
|
4
6
|
from xync_schema import models
|
|
5
7
|
from xync_schema.models import Cur, Ex
|
|
6
8
|
|
|
7
|
-
from xync_client.Abc.Ex import
|
|
9
|
+
from xync_client.Abc.Ex import BaseClient
|
|
8
10
|
from xync_client.loader import PG_DSN
|
|
9
11
|
|
|
10
12
|
|
|
11
|
-
class Client(
|
|
13
|
+
class Client(BaseClient):
|
|
14
|
+
headers = {"accept-language": "ru,en;q=0.9"}
|
|
15
|
+
|
|
12
16
|
async def curs(self) -> dict[str, str]:
|
|
13
17
|
curs = (await self._post("/v1/p2p/pub/currency/queryAllCoinAndFiat"))["data"]["fiatInfoRespList"]
|
|
14
18
|
return {cur["fiatCode"]: cur["fiatCode"] for cur in curs}
|
|
@@ -18,7 +22,13 @@ class Client(ExClient):
|
|
|
18
22
|
return {coin["coinCode"]: coin["coinCode"] for coin in coins}
|
|
19
23
|
|
|
20
24
|
async def pms(self, cur: Cur = None) -> dict[int, dict]:
|
|
21
|
-
curs = (await self._post("
|
|
25
|
+
# curs = (await self._post("pub/currency/queryAllCoinAndFiat"))["data"]["fiatInfoRespList"]
|
|
26
|
+
p = subprocess.Popen(
|
|
27
|
+
["node", "req.mjs", "user/queryPaymethods", '{"languageType":6}', self.headers], stdout=subprocess.PIPE
|
|
28
|
+
)
|
|
29
|
+
out = p.stdout.read().decode()
|
|
30
|
+
curs: list[dict] = json.loads(out)
|
|
31
|
+
|
|
22
32
|
pmcurs = {cur["fiatCode"]: cur["paymethodInfo"] for cur in curs}
|
|
23
33
|
pp = {}
|
|
24
34
|
[
|
|
@@ -69,7 +79,7 @@ async def main():
|
|
|
69
79
|
# await cl.curs()
|
|
70
80
|
# await cl.coins()
|
|
71
81
|
# await cl.ads("BTC", "RUB", True, [1, 289, 375])
|
|
72
|
-
|
|
82
|
+
await cl.pms()
|
|
73
83
|
# await cl.cur_pms_map()
|
|
74
84
|
await cl.set_pmcurexs()
|
|
75
85
|
await cl.set_coinexs()
|
|
@@ -7,14 +7,18 @@ from x_model import init_db
|
|
|
7
7
|
from xync_schema import models
|
|
8
8
|
from xync_schema.models import Coin, Cur, Pm, Ad, Ex, Curex
|
|
9
9
|
|
|
10
|
-
from xync_client.Abc import
|
|
10
|
+
from xync_client.Abc.Base import MapOfIdsList
|
|
11
|
+
from xync_client.Abc.Ex import BaseExClient
|
|
11
12
|
from xync_client.loader import PG_DSN
|
|
12
13
|
|
|
13
14
|
|
|
14
|
-
class PublicClient(
|
|
15
|
+
class PublicClient(BaseExClient):
|
|
16
|
+
async def cur_pms_map(self) -> MapOfIdsList:
|
|
17
|
+
pass
|
|
18
|
+
|
|
15
19
|
async def curs(self) -> list[Cur]:
|
|
16
20
|
curs = await self._post("/json_svr/buy_crypto_fiat_setting")
|
|
17
|
-
curs = [
|
|
21
|
+
curs = [cur["fiat"] for cur in curs if cur["p2p"]]
|
|
18
22
|
curexs = [Curex(cur=c, ex=self.ex) for c in curs]
|
|
19
23
|
await Curex.bulk_create(curexs, ignore_conflicts=True)
|
|
20
24
|
return curs
|
|
@@ -4,11 +4,15 @@ from x_model import init_db
|
|
|
4
4
|
from xync_schema import models
|
|
5
5
|
from xync_schema.models import Coin, Cur, Pm, Ad, Ex, Curex
|
|
6
6
|
|
|
7
|
-
from xync_client.Abc import
|
|
7
|
+
from xync_client.Abc.Base import MapOfIdsList
|
|
8
|
+
from xync_client.Abc.Ex import BaseExClient
|
|
8
9
|
from xync_client.loader import PG_DSN
|
|
9
10
|
|
|
10
11
|
|
|
11
|
-
class
|
|
12
|
+
class ExClient(BaseExClient):
|
|
13
|
+
async def cur_pms_map(self) -> MapOfIdsList:
|
|
14
|
+
pass
|
|
15
|
+
|
|
12
16
|
async def curs(self) -> list[Cur]:
|
|
13
17
|
curs = (await self._get("/_api/otc/dictionary/getData", {"type": "LEGAL"}))["data"]
|
|
14
18
|
curs = [(await Cur.update_or_create(ticker=cur["typeCode"]))[0] for cur in curs]
|
|
@@ -34,7 +38,7 @@ class PublicClient(BasePublicClient):
|
|
|
34
38
|
async def main():
|
|
35
39
|
_ = await init_db(PG_DSN, models, True)
|
|
36
40
|
bg = await Ex.get(name="KuCoin")
|
|
37
|
-
cl =
|
|
41
|
+
cl = ExClient(bg)
|
|
38
42
|
# await cl.curs()
|
|
39
43
|
# await cl.coins()
|
|
40
44
|
await cl.pms()
|
xync_client-0.0.11.dev0/xync_client/Okx/pub.py → xync_client-0.0.11.dev4/xync_client/Okx/ex.py
RENAMED
|
@@ -2,23 +2,24 @@ from asyncio import run
|
|
|
2
2
|
|
|
3
3
|
from x_model import init_db
|
|
4
4
|
from xync_schema import models
|
|
5
|
-
from xync_schema.models import Coin, Cur, Pm, Ad, Ex
|
|
5
|
+
from xync_schema.models import Coin, Cur, Pm, Ad, Ex
|
|
6
6
|
|
|
7
|
-
from xync_client.Abc import
|
|
7
|
+
from xync_client.Abc.Base import MapOfIdsList, ListOfDicts
|
|
8
|
+
from xync_client.Abc.Ex import BaseExClient
|
|
8
9
|
from xync_client.loader import PG_DSN
|
|
9
10
|
|
|
10
11
|
|
|
11
|
-
class
|
|
12
|
+
class ExClient(BaseExClient):
|
|
13
|
+
async def cur_pms_map(self) -> MapOfIdsList:
|
|
14
|
+
pass
|
|
15
|
+
|
|
12
16
|
async def curs(self) -> list[Cur]:
|
|
13
17
|
curs = (await self._get("/v3/users/common/list/currencies"))["data"]
|
|
14
|
-
curs = [(await Cur.update_or_create(ticker=cur["isoCode"]))[0] for cur in curs]
|
|
15
|
-
curexs = [Curex(cur=c, ex=self.ex) for c in curs]
|
|
16
|
-
await Curex.bulk_create(curexs, ignore_conflicts=True)
|
|
17
18
|
return curs
|
|
18
19
|
|
|
19
20
|
async def coins(self, cur: Cur = None) -> list[Coin]: ...
|
|
20
21
|
|
|
21
|
-
async def pms(self, cur: Cur = None) ->
|
|
22
|
+
async def pms(self, cur: Cur = None) -> ListOfDicts:
|
|
22
23
|
pmcurs = {
|
|
23
24
|
cur.ticker: (await self._get("/v3/c2c/configs/receipt/templates", {"quoteCurrency": cur.ticker}))["data"]
|
|
24
25
|
for cur in await self.curs()
|
|
@@ -35,7 +36,7 @@ class PublicClient(BasePublicClient):
|
|
|
35
36
|
async def main():
|
|
36
37
|
_ = await init_db(PG_DSN, models, True)
|
|
37
38
|
bg = await Ex.get(name="Okx")
|
|
38
|
-
cl =
|
|
39
|
+
cl = ExClient(bg)
|
|
39
40
|
# await cl.curs()
|
|
40
41
|
# await cl.coins()
|
|
41
42
|
await cl.pms()
|
|
@@ -5,7 +5,7 @@ from x_client.http import Client as HttpClient
|
|
|
5
5
|
from xync_schema.models import User, Cur, Order, Coin, OrderStatus, Pmex
|
|
6
6
|
from xync_schema.pydantic import FiatNew
|
|
7
7
|
|
|
8
|
-
from xync_client.Abc.Agent import
|
|
8
|
+
from xync_client.Abc.Agent import BaseAgentClient
|
|
9
9
|
from xync_client.TgWallet.pyro import PyroClient
|
|
10
10
|
|
|
11
11
|
|
|
@@ -17,16 +17,13 @@ class Status(IntEnum):
|
|
|
17
17
|
ALL_ACTIVE = OrderStatus.active
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
class
|
|
20
|
+
class AgentClient(BaseAgentClient):
|
|
21
21
|
async def order_request(self, ad_id: int, amount: float) -> Order:
|
|
22
22
|
pass
|
|
23
23
|
|
|
24
24
|
async def _get_auth_hdrs(self) -> dict[str, str]:
|
|
25
25
|
pyro = PyroClient(self.agent)
|
|
26
26
|
init_data = await pyro.get_init_data()
|
|
27
|
-
# async with ClientSession(self.agent.ex.url_login) as sess:
|
|
28
|
-
# resp = await sess.post('/api/v1/users/auth/', data=init_data, headers={'content-type': 'application/json;charset=UTF-8'})
|
|
29
|
-
# tokens = await resp.json()
|
|
30
27
|
tokens = HttpClient("walletbot.me")._post("/api/v1/users/auth/", init_data)
|
|
31
28
|
return {"Wallet-Authorization": tokens["jwt"], "Authorization": "Bearer " + tokens["value"]}
|
|
32
29
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from aiohttp import ClientResponse
|
|
4
|
+
from aiohttp.http_exceptions import HttpProcessingError
|
|
5
|
+
from x_client.http import Client as HttpClient
|
|
6
|
+
from xync_client.Abc.Auth import BaseAuthClient
|
|
7
|
+
from xync_schema.models import Agent
|
|
8
|
+
|
|
9
|
+
from xync_client.TgWallet.pyro import PyroClient
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class AuthClient(BaseAuthClient):
|
|
13
|
+
def __init__(self, agent: Agent):
|
|
14
|
+
self.meth = {
|
|
15
|
+
"GET": self._get,
|
|
16
|
+
"POST": self._post,
|
|
17
|
+
"DELETE": self._delete,
|
|
18
|
+
}
|
|
19
|
+
super().__init__(agent)
|
|
20
|
+
|
|
21
|
+
async def _get_auth_hdrs(self) -> dict[str, str]:
|
|
22
|
+
pyro = PyroClient(self.agent)
|
|
23
|
+
init_data = await pyro.get_init_data()
|
|
24
|
+
tokens = HttpClient("walletbot.me")._post("/api/v1/users/auth/", init_data)
|
|
25
|
+
return {"Wallet-Authorization": tokens["jwt"], "Authorization": "Bearer " + tokens["value"]}
|
|
26
|
+
|
|
27
|
+
async def login(self) -> None:
|
|
28
|
+
auth_hdrs: dict[str, str] = await self._get_auth_hdrs()
|
|
29
|
+
self.session.headers.update(auth_hdrs)
|
|
30
|
+
|
|
31
|
+
async def _proc(self, resp: ClientResponse, data: dict = None) -> dict | str:
|
|
32
|
+
try:
|
|
33
|
+
return await super()._proc(resp)
|
|
34
|
+
except HttpProcessingError as e:
|
|
35
|
+
if e.code == 401:
|
|
36
|
+
logging.warning(e)
|
|
37
|
+
await self.login()
|
|
38
|
+
res = await self.meth[resp.method](resp.url.path, data)
|
|
39
|
+
return res
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from xync_client.Abc.Auth import BaseAuthClient
|
|
2
|
+
from xync_schema.models import Pm
|
|
3
|
+
|
|
4
|
+
from xync_client.Abc.Ex import BaseExClient
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ExClient(BaseExClient, BaseAuthClient):
|
|
8
|
+
async def curs(self) -> dict[str, str]:
|
|
9
|
+
coins_curs = await self._post("/p2p/public-api/v2/currency/all-supported")
|
|
10
|
+
return {c["code"]: c["code"] for c in coins_curs["data"]["fiat"]}
|
|
11
|
+
|
|
12
|
+
async def coins(self) -> dict[str, str]:
|
|
13
|
+
coins_curs = await self._post("/p2p/public-api/v2/currency/all-supported")
|
|
14
|
+
return {c["code"]: c["code"] for c in coins_curs["data"]["crypto"]}
|
|
15
|
+
|
|
16
|
+
async def _pms(self, cur: str = "RUB") -> dict[str, dict]:
|
|
17
|
+
pms = await self._post("/p2p/public-api/v3/payment-details/get-methods/by-currency-code", {"currencyCode": cur})
|
|
18
|
+
return {pm["code"]: {"name": pm["nameEng"]} for pm in pms["data"]}
|
|
19
|
+
|
|
20
|
+
async def pms(self) -> dict[str, dict]:
|
|
21
|
+
pms = {}
|
|
22
|
+
for cur in await self.curs():
|
|
23
|
+
for k, pm in (await self._pms(cur)).items():
|
|
24
|
+
pms.update({k: pm})
|
|
25
|
+
return pms
|
|
26
|
+
|
|
27
|
+
async def cur_pms_map(self) -> dict[str, list[str]]:
|
|
28
|
+
return {cur: list(await self._pms(cur)) for cur in await self.curs()}
|
|
29
|
+
|
|
30
|
+
async def ads(self, coin: str, cur: str, is_sell: bool, pms: list[Pm] = None) -> list[dict]:
|
|
31
|
+
params = {
|
|
32
|
+
"baseCurrencyCode": coin,
|
|
33
|
+
"quoteCurrencyCode": cur,
|
|
34
|
+
"offerType": "SALE" if is_sell else "PURCHASE",
|
|
35
|
+
"offset": 0,
|
|
36
|
+
"limit": 10,
|
|
37
|
+
# ,"merchantVerified":"TRUSTED"
|
|
38
|
+
}
|
|
39
|
+
ads = await self._post("/p2p/public-api/v2/offer/depth-of-market/", params)
|
|
40
|
+
return ads
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from enum import StrEnum, IntEnum
|
|
2
|
+
from xync_schema.models import Order, OrderStatus
|
|
3
|
+
|
|
4
|
+
from xync_client.Abc.Order import BaseOrderClient
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Exceptions(StrEnum):
|
|
8
|
+
PM_KYC = "OFFER_FIAT_COUNTRY_NOT_SUPPORTED_BY_USER_KYC_COUNTRY"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Status(IntEnum):
|
|
12
|
+
ALL_ACTIVE = OrderStatus.active
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class OrderClient(BaseOrderClient):
|
|
16
|
+
# 2
|
|
17
|
+
async def cancel_request(self) -> Order:
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
# 2
|
|
21
|
+
async def accept_request(self) -> bool:
|
|
22
|
+
approve = await self._post(
|
|
23
|
+
"/p2p/public-api/v2/offer/order/accept",
|
|
24
|
+
{"orderId": self.order.id, "type": {True: "SALE", False: "BUY"}[self.im_seller]},
|
|
25
|
+
)
|
|
26
|
+
return approve
|
|
27
|
+
|
|
28
|
+
# 2
|
|
29
|
+
async def reject_request(self) -> bool:
|
|
30
|
+
reject = await self._post("/p2p/public-api/v2/offer/order/cancel/by-seller", {"orderId": self.order.id})
|
|
31
|
+
return reject
|
|
32
|
+
|
|
33
|
+
# 2
|
|
34
|
+
async def mark_payed(self, receipt):
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
# 2
|
|
38
|
+
async def cancel_order(self) -> bool:
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
# 7 - [S] payment received confirm
|
|
42
|
+
async def confirm(self) -> bool:
|
|
43
|
+
payment_confirm = await self._post("/p2p/public-api/v2/payment-details/confirm", {"orderId": self.order.id})
|
|
44
|
+
return payment_confirm
|
|
45
|
+
|
|
46
|
+
# 2
|
|
47
|
+
async def start_appeal(self, file) -> bool:
|
|
48
|
+
pass
|
|
49
|
+
|
|
50
|
+
# 2
|
|
51
|
+
async def dispute_appeal(self, file) -> bool:
|
|
52
|
+
pass
|
|
53
|
+
|
|
54
|
+
async def cancel_appeal(self) -> bool:
|
|
55
|
+
pass
|
|
56
|
+
|
|
57
|
+
# 2
|
|
58
|
+
async def send_order_msg(self, msg: str, file=None) -> bool:
|
|
59
|
+
pass
|
|
60
|
+
|
|
61
|
+
# 2
|
|
62
|
+
async def send_appeal_msg(self, file, msg: str = None) -> bool:
|
|
63
|
+
pass
|
|
64
|
+
|
|
65
|
+
# 2
|
|
66
|
+
async def _upload_file(self, order_id: int, path_to_file: str):
|
|
67
|
+
url = f"/public-api/v2/file-storage/file/upload?orderId={order_id}&uploadType=UPLOAD_BUYER_PAYMENT_RECEIPT"
|
|
68
|
+
data = {"file": open(path_to_file, "rb")}
|
|
69
|
+
upload_file = await self._post(url, data)
|
|
70
|
+
return upload_file
|
|
71
|
+
|
|
72
|
+
# 19 - order_paid
|
|
73
|
+
async def order_paid(self, order_id: str, file: dict):
|
|
74
|
+
paid = await self._post(
|
|
75
|
+
"/p2p/public-api/v2/offer/order/confirm-sending-payment", {"orderId": order_id, "paymentReceipt": file}
|
|
76
|
+
)
|
|
77
|
+
return paid
|
|
File without changes
|
|
@@ -19,14 +19,20 @@ xync_client.egg-info/dependency_links.txt
|
|
|
19
19
|
xync_client.egg-info/requires.txt
|
|
20
20
|
xync_client.egg-info/top_level.txt
|
|
21
21
|
xync_client/Abc/Agent.py
|
|
22
|
+
xync_client/Abc/Auth.py
|
|
23
|
+
xync_client/Abc/Base.py
|
|
22
24
|
xync_client/Abc/Ex.py
|
|
23
25
|
xync_client/Abc/Order.py
|
|
26
|
+
xync_client/Abc/Test.py
|
|
27
|
+
xync_client/Binance/__init__.py
|
|
24
28
|
xync_client/Binance/binance_async.py
|
|
25
29
|
xync_client/Binance/earn_api.py
|
|
26
30
|
xync_client/Binance/ex.py
|
|
27
31
|
xync_client/Binance/exceptions.py
|
|
28
32
|
xync_client/Binance/sapi.py
|
|
29
33
|
xync_client/Binance/web_c2c.py
|
|
34
|
+
xync_client/BingX/ex.py
|
|
35
|
+
xync_client/BingX/test/main.py
|
|
30
36
|
xync_client/BitGet/__init__.py
|
|
31
37
|
xync_client/BitGet/agent.py
|
|
32
38
|
xync_client/BitGet/ex.py
|
|
@@ -41,8 +47,9 @@ xync_client/Htx/earn.py
|
|
|
41
47
|
xync_client/Htx/ex.py
|
|
42
48
|
xync_client/KuCoin/pub.py
|
|
43
49
|
xync_client/KuCoin/web.py
|
|
44
|
-
xync_client/Okx/
|
|
50
|
+
xync_client/Okx/ex.py
|
|
45
51
|
xync_client/TgWallet/agent.py
|
|
52
|
+
xync_client/TgWallet/auth.py
|
|
46
53
|
xync_client/TgWallet/ex.py
|
|
47
54
|
xync_client/TgWallet/order.py
|
|
48
55
|
xync_client/TgWallet/pyro.py
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
|
|
3
|
-
from aiohttp import ClientResponse
|
|
4
|
-
from aiohttp.http_exceptions import HttpProcessingError
|
|
5
|
-
from x_client.http import Client
|
|
6
|
-
from xync_schema.models import Pm, Agent, Ex
|
|
7
|
-
|
|
8
|
-
from xync_client.Abc.Ex import ExClient
|
|
9
|
-
from xync_client.TgWallet.pyro import PyroClient
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class PublicClient(ExClient):
|
|
13
|
-
def __init__(self, agent: Agent):
|
|
14
|
-
self.agent: Agent = agent
|
|
15
|
-
assert isinstance(agent.ex, Ex), "`ex` should be fetched in `agent`"
|
|
16
|
-
assert agent.ex.host_p2p, "`ex.host_p2p` shouldn't be empty"
|
|
17
|
-
self.meth = {
|
|
18
|
-
"GET": self._get,
|
|
19
|
-
"POST": self._post,
|
|
20
|
-
}
|
|
21
|
-
super().__init__(agent.ex)
|
|
22
|
-
|
|
23
|
-
async def _get_auth_hdrs(self) -> dict[str, str]:
|
|
24
|
-
pyro = PyroClient(self.agent)
|
|
25
|
-
init_data = await pyro.get_init_data()
|
|
26
|
-
# async with ClientSession(self.agent.ex.url_login) as sess:
|
|
27
|
-
# resp = await sess.post('/api/v1/users/auth/', data=init_data, headers={'content-type': 'application/json;charset=UTF-8'})
|
|
28
|
-
# tokens = await resp.json()
|
|
29
|
-
tokens = Client("walletbot.me")._post("/api/v1/users/auth/", init_data)
|
|
30
|
-
return {"Wallet-Authorization": tokens["jwt"], "Authorization": "Bearer " + tokens["value"]}
|
|
31
|
-
|
|
32
|
-
async def login(self) -> None:
|
|
33
|
-
auth_hdrs: dict[str, str] = await self._get_auth_hdrs()
|
|
34
|
-
self.session.headers.update(auth_hdrs)
|
|
35
|
-
|
|
36
|
-
async def _proc(self, resp: ClientResponse, data: dict = None) -> dict | str:
|
|
37
|
-
try:
|
|
38
|
-
return await super()._proc(resp)
|
|
39
|
-
except HttpProcessingError as e:
|
|
40
|
-
if e.code == 401:
|
|
41
|
-
logging.warning(e)
|
|
42
|
-
await self.login()
|
|
43
|
-
res = await self.meth[resp.method](resp.url.path, data)
|
|
44
|
-
return res
|
|
45
|
-
|
|
46
|
-
async def curs(self) -> dict[str, str]:
|
|
47
|
-
coins_curs = await self._post("/p2p/public-api/v2/currency/all-supported")
|
|
48
|
-
return {c["code"]: c["code"] for c in coins_curs["data"]["fiat"]}
|
|
49
|
-
|
|
50
|
-
async def coins(self) -> dict[str, str]:
|
|
51
|
-
coins_curs = await self._post("/p2p/public-api/v2/currency/all-supported")
|
|
52
|
-
return {c["code"]: c["code"] for c in coins_curs["data"]["crypto"]}
|
|
53
|
-
|
|
54
|
-
async def _pms(self, cur: str = "RUB") -> dict[str, dict]:
|
|
55
|
-
pms = await self._post("/p2p/public-api/v3/payment-details/get-methods/by-currency-code", {"currencyCode": cur})
|
|
56
|
-
return {pm["code"]: {"name": pm["nameEng"]} for pm in pms["data"]}
|
|
57
|
-
|
|
58
|
-
async def pms(self) -> dict[str, dict]:
|
|
59
|
-
pms = {}
|
|
60
|
-
for cur in await self.curs():
|
|
61
|
-
for k, pm in (await self._pms(cur)).items():
|
|
62
|
-
pms.update({k: pm})
|
|
63
|
-
return pms
|
|
64
|
-
|
|
65
|
-
async def cur_pms_map(self) -> dict[str, list[str]]:
|
|
66
|
-
return {cur: list(await self._pms(cur)) for cur in await self.curs()}
|
|
67
|
-
|
|
68
|
-
async def ads(self, coin: str, cur: str, is_sell: bool, pms: list[Pm] = None) -> list[dict]:
|
|
69
|
-
params = {
|
|
70
|
-
"baseCurrencyCode": coin,
|
|
71
|
-
"quoteCurrencyCode": cur,
|
|
72
|
-
"offerType": "SALE" if is_sell else "PURCHASE",
|
|
73
|
-
"offset": 0,
|
|
74
|
-
"limit": 10,
|
|
75
|
-
# ,"merchantVerified":"TRUSTED"
|
|
76
|
-
}
|
|
77
|
-
ads = await self._post("/p2p/public-api/v2/offer/depth-of-market/", params)
|
|
78
|
-
return ads
|
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
from enum import StrEnum, IntEnum
|
|
2
|
-
from typing import Literal
|
|
3
|
-
|
|
4
|
-
from x_client.http import Client
|
|
5
|
-
from xync_schema.models import User, Cur, Order, Coin, OrderStatus, Pmex
|
|
6
|
-
from xync_schema.pydantic import FiatNew
|
|
7
|
-
|
|
8
|
-
from xync_client.Abc.Agent import Client as BaseClient
|
|
9
|
-
from xync_client.TgWallet.pyro import PyroClient
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class Exceptions(StrEnum):
|
|
13
|
-
PM_KYC = "OFFER_FIAT_COUNTRY_NOT_SUPPORTED_BY_USER_KYC_COUNTRY"
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class Status(IntEnum):
|
|
17
|
-
ALL_ACTIVE = OrderStatus.active
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class AgentClient(BaseClient):
|
|
21
|
-
async def _get_auth_hdrs(self) -> dict[str, str]:
|
|
22
|
-
pyro = PyroClient(self.agent)
|
|
23
|
-
init_data = await pyro.get_init_data()
|
|
24
|
-
# async with ClientSession(self.agent.ex.url_login) as sess:
|
|
25
|
-
# resp = await sess.post('/api/v1/users/auth/', data=init_data, headers={'content-type': 'application/json;charset=UTF-8'})
|
|
26
|
-
# tokens = await resp.json()
|
|
27
|
-
tokens = Client("walletbot.me")._post("/api/v1/users/auth/", init_data)
|
|
28
|
-
return {"Wallet-Authorization": tokens["jwt"], "Authorization": "Bearer " + tokens["value"]}
|
|
29
|
-
|
|
30
|
-
async def get_orders(
|
|
31
|
-
self, stauts: OrderStatus = OrderStatus.active, coin: Coin = None, cur: Cur = None, is_sell: bool = None
|
|
32
|
-
) -> list[Order]:
|
|
33
|
-
orders = await self._post(
|
|
34
|
-
"/p2p/public-api/v2/offer/order/history/get-by-user-id",
|
|
35
|
-
{"offset": 0, "limit": 100, "filter": {"status": Status(stauts)}}, # "limit": 20
|
|
36
|
-
)
|
|
37
|
-
return orders
|
|
38
|
-
|
|
39
|
-
async def order_request(self, ad_id: int, amount: float) -> Order: ...
|
|
40
|
-
|
|
41
|
-
async def my_fiats(self, cur: Cur = None) -> dict:
|
|
42
|
-
fiats = await self._post("/p2p/public-api/v3/payment-details/get/by-user-id")
|
|
43
|
-
fiats = {fiat["id"]: fiat for fiat in fiats["data"]}
|
|
44
|
-
return fiats
|
|
45
|
-
|
|
46
|
-
async def fiat_new(self, fiat: FiatNew):
|
|
47
|
-
pmex = await Pmex.get_or_create(pm_id=fiat.pm_id, ex=self.agent.ex) # .prefetch_related('pm')
|
|
48
|
-
cur = await Cur[fiat.cur_id]
|
|
49
|
-
add_fiat = await self._post(
|
|
50
|
-
"/p2p/public-api/v3/payment-details/create",
|
|
51
|
-
{
|
|
52
|
-
"paymentMethodCode": pmex.exid,
|
|
53
|
-
"currencyCode": cur.ticker,
|
|
54
|
-
"name": fiat.name,
|
|
55
|
-
"attributes": {"version": "V1", "values": [{"name": "PAYMENT_DETAILS_NUMBER", "value": fiat.detail}]},
|
|
56
|
-
},
|
|
57
|
-
)
|
|
58
|
-
return add_fiat
|
|
59
|
-
|
|
60
|
-
# 7 - fiat_edit
|
|
61
|
-
async def fiat_upd(self, fiat_id: int, name: str, detail: str):
|
|
62
|
-
edit_fiat = await self._post(
|
|
63
|
-
"/p2p/public-api/v3/payment-details/edit",
|
|
64
|
-
{
|
|
65
|
-
"id": fiat_id,
|
|
66
|
-
# "paymentMethodCode": code_pms,
|
|
67
|
-
# "currencyCode": cur,
|
|
68
|
-
"name": name,
|
|
69
|
-
"attributes": {"version": "V1", "values": [{"name": "PAYMENT_DETAILS_NUMBER", "value": detail}]},
|
|
70
|
-
},
|
|
71
|
-
)
|
|
72
|
-
return edit_fiat
|
|
73
|
-
|
|
74
|
-
async def fiat_del(self, fiat_id: int):
|
|
75
|
-
del_fiat = await self._post("/p2p/public-api/v3/payment-details/delete", {"id": fiat_id})
|
|
76
|
-
return del_fiat
|
|
77
|
-
|
|
78
|
-
async def ad_switch(self) -> bool:
|
|
79
|
-
pass
|
|
80
|
-
|
|
81
|
-
async def ads_switch(self) -> bool:
|
|
82
|
-
pass
|
|
83
|
-
|
|
84
|
-
async def get_user(self, user_id) -> User:
|
|
85
|
-
pass
|
|
86
|
-
|
|
87
|
-
async def send_user_msg(self, msg: str, file=None) -> bool:
|
|
88
|
-
pass
|
|
89
|
-
|
|
90
|
-
async def block_user(self, is_blocked: bool = True) -> bool:
|
|
91
|
-
pass
|
|
92
|
-
|
|
93
|
-
async def rate_user(self, positive: bool) -> bool:
|
|
94
|
-
pass
|
|
95
|
-
|
|
96
|
-
# base_url = 'https://p2p.walletbot.me'
|
|
97
|
-
# middle_url = '/p2p/'
|
|
98
|
-
|
|
99
|
-
# 1: all_curs
|
|
100
|
-
async def all_curs(self):
|
|
101
|
-
coins_curs = await self._post("/p2p/public-api/v2/currency/all-supported")
|
|
102
|
-
curs = [c["code"] for c in coins_curs["data"]["fiat"]]
|
|
103
|
-
return curs
|
|
104
|
-
|
|
105
|
-
# 2: all_coins
|
|
106
|
-
async def all_coins(self):
|
|
107
|
-
coins_curs = await self._post("/p2p/public-api/v2/currency/all-supported")
|
|
108
|
-
coins = [c["code"] for c in coins_curs["data"]["crypto"]]
|
|
109
|
-
return coins
|
|
110
|
-
|
|
111
|
-
# 3: all_coins
|
|
112
|
-
async def all_pms(self):
|
|
113
|
-
pms = await self._post(
|
|
114
|
-
"/p2p/public-api/v3/payment-details/get-methods/by-currency-code", {"currencyCode": "RUB"}
|
|
115
|
-
)
|
|
116
|
-
return pms["data"]
|
|
117
|
-
|
|
118
|
-
# 4: all_ads
|
|
119
|
-
async def get_ads(
|
|
120
|
-
self, coin: str = "TON", cur: str = "RUB", tt: str = "SALE", offset: int = 0, limit: int = 100
|
|
121
|
-
) -> dict:
|
|
122
|
-
params = {
|
|
123
|
-
"baseCurrencyCode": coin,
|
|
124
|
-
"quoteCurrencyCode": cur,
|
|
125
|
-
"offerType": tt,
|
|
126
|
-
"offset": offset,
|
|
127
|
-
"limit": limit,
|
|
128
|
-
} # ,"merchantVerified":"TRUSTED"
|
|
129
|
-
ads = await self._post("/p2p/public-api/v2/offer/depth-of-market/", params)
|
|
130
|
-
return ads
|
|
131
|
-
|
|
132
|
-
# 9 - my_ads
|
|
133
|
-
async def my_ads(self, status: Literal["INACTIVE", "ACTIVE"] = None):
|
|
134
|
-
ads = await self._post(
|
|
135
|
-
"/p2p/public-api/v2/offer/user-own/list", {"offset": 0, "limit": 20, "offerType": "SALE"}
|
|
136
|
-
)
|
|
137
|
-
return [ad for ad in ads["data"] if ad["status"] == status] if status else ads
|
|
138
|
-
|
|
139
|
-
# 10 - ad_new
|
|
140
|
-
async def ad_new(self, fiats: list[int], amount: int, coin: str = "TON", cur: str = "RUB", tt: str = "SALE"):
|
|
141
|
-
create = await self._post(
|
|
142
|
-
"/p2p/public-api/v2/offer/create",
|
|
143
|
-
{
|
|
144
|
-
"type": tt,
|
|
145
|
-
"initVolume": {"currencyCode": coin, "amount": f"{amount}"},
|
|
146
|
-
"orderRoundingRequired": False,
|
|
147
|
-
"price": {"type": "FLOATING", "baseCurrencyCode": coin, "quoteCurrencyCode": cur, "value": "120"},
|
|
148
|
-
"orderAmountLimits": {"min": "500", "max": "2000"},
|
|
149
|
-
"paymentConfirmTimeout": "PT15M",
|
|
150
|
-
"comment": "",
|
|
151
|
-
"paymentDetailsIds": fiats,
|
|
152
|
-
},
|
|
153
|
-
)
|
|
154
|
-
return create
|
|
155
|
-
|
|
156
|
-
# 11 - ad_upd
|
|
157
|
-
async def ad_upd(self, typ: str, offer_id: int, fiats: list[int], amount: int):
|
|
158
|
-
upd = await self._post(
|
|
159
|
-
"/p2p/public-api/v2/offer/edit",
|
|
160
|
-
{
|
|
161
|
-
"offerId": offer_id,
|
|
162
|
-
"paymentConfirmTimeout": "PT15M",
|
|
163
|
-
"type": typ,
|
|
164
|
-
"orderRoundingRequired": False,
|
|
165
|
-
"price": {"type": "FLOATING", "value": "120"},
|
|
166
|
-
"orderAmountLimits": {"min": "500", "max": "2000"},
|
|
167
|
-
"comment": "",
|
|
168
|
-
"volume": f"{amount}",
|
|
169
|
-
"paymentDetailsIds": fiats,
|
|
170
|
-
},
|
|
171
|
-
)
|
|
172
|
-
return upd
|
|
173
|
-
|
|
174
|
-
# 12 - ad_del
|
|
175
|
-
async def ad_del(self, typ: str, offer_id: int):
|
|
176
|
-
ad_del = await self._post("/p2p/public-api/v2/offer/delete", {"type": typ, "offerId": offer_id})
|
|
177
|
-
return ad_del
|
|
178
|
-
|
|
179
|
-
# 13 - ad_on
|
|
180
|
-
async def ad_on(self, typ: str, offer_id: int):
|
|
181
|
-
active = await self._post("/p2p/public-api/v2/offer/activate", {"type": typ, "offerId": offer_id})
|
|
182
|
-
return active
|
|
183
|
-
|
|
184
|
-
# 14 - ad_off
|
|
185
|
-
async def ad_off(self, typ: str, offer_id: int) -> dict[str, str]:
|
|
186
|
-
off = await self._post("/p2p/public-api/v2/offer/deactivate", {"type": typ, "offerId": offer_id})
|
|
187
|
-
return off
|
|
188
|
-
|
|
189
|
-
# 15 - order_approve
|
|
190
|
-
async def order_approve(self, order_id: int, typ: str):
|
|
191
|
-
approve = await self._post("/p2p/public-api/v2/offer/order/accept", {"orderId": order_id, "type": typ})
|
|
192
|
-
return approve
|
|
193
|
-
|
|
194
|
-
# 16 - order_reject
|
|
195
|
-
async def order_reject(self, order_id: str):
|
|
196
|
-
reject = await self._post("/p2p/public-api/v2/offer/order/cancel/by-seller", {"orderId": order_id})
|
|
197
|
-
return reject
|
|
198
|
-
|
|
199
|
-
async def upload_file(self, order_id: int, path_to_file: str):
|
|
200
|
-
url = f"public-api/v2/file-storage/file/upload?orderId={order_id}&uploadType=UPLOAD_BUYER_PAYMENT_RECEIPT"
|
|
201
|
-
data = {"file": open(path_to_file, "rb")}
|
|
202
|
-
upload_file = await self._post(url, data)
|
|
203
|
-
return upload_file
|
|
204
|
-
|
|
205
|
-
# 19 - order_paid
|
|
206
|
-
async def order_paid(self, order_id: str, file: dict):
|
|
207
|
-
paid = await self._post(
|
|
208
|
-
"/p2p/public-api/v2/offer/order/confirm-sending-payment", {"orderId": order_id, "paymentReceipt": file}
|
|
209
|
-
)
|
|
210
|
-
return paid
|
|
211
|
-
|
|
212
|
-
# 20 - order_payment_confirm
|
|
213
|
-
async def order_payment_confirm(self, order_id: str):
|
|
214
|
-
payment_confirm = await self._post("/p2p/public-api/v2/payment-details/confirm", {"orderId": order_id})
|
|
215
|
-
return payment_confirm
|
|
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.dev0/xync_client → xync_client-0.0.11.dev4/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
|
{xync_client-0.0.11.dev0 → xync_client-0.0.11.dev4}/xync_client.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|