xync-client 0.0.3__tar.gz → 0.0.7.dev0__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.3/xync_client.egg-info → xync_client-0.0.7.dev0}/PKG-INFO +1 -1
- xync_client-0.0.3/tests/test_wallet.py → xync_client-0.0.7.dev0/tests/wallet/test_agent.py +14 -49
- xync_client-0.0.7.dev0/tests/wallet/test_ex.py +67 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client/Abc/Agent.py +2 -1
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client/Abc/Ex.py +7 -3
- xync_client-0.0.3/xync_client/Binance/web.py → xync_client-0.0.7.dev0/xync_client/Binance/ex.py +27 -11
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client/Binance/sapi.py +1 -1
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client/Bybit/web_earn.py +1 -1
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client/Htx/ex.py +1 -1
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client/TgWallet/agent.py +7 -8
- xync_client-0.0.7.dev0/xync_client/TgWallet/ex.py +78 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0/xync_client.egg-info}/PKG-INFO +1 -1
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client.egg-info/SOURCES.txt +3 -8
- xync_client-0.0.3/tests/test_abc.py +0 -8
- xync_client-0.0.3/tests/test_binance.py +0 -14
- xync_client-0.0.3/tests/test_bybit.py +0 -83
- xync_client-0.0.3/tests/test_bybit_p2p.py +0 -193
- xync_client-0.0.3/tests/test_gate.py +0 -38
- xync_client-0.0.3/tests/test_htx_p2p.py +0 -0
- xync_client-0.0.3/xync_client/TgWallet/ex.py +0 -101
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/.env.sample +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/.gitignore +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/.pre-commit-config.yaml +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/README.md +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/makefile +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/pyproject.toml +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/setup.cfg +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/tests/__init__.py +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client/Abc/Order.py +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client/Binance/binance_async.py +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client/Binance/earn_api.py +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client/Binance/exceptions.py +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client/Binance/web_c2c.py +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client/BitGet/pub.py +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client/Bybit/web_p2p.py +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client/Gate/premarket.py +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client/Gate/pub.py +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client/Htx/agent.py +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client/Htx/earn.py +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client/KuCoin/pub.py +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client/KuCoin/web.py +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client/Okx/pub.py +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client/TgWallet/pyro.py +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client/TgWallet/web.py +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client/__init__.py +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client/loader.py +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client.egg-info/dependency_links.txt +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client.egg-info/requires.txt +0 -0
- {xync_client-0.0.3 → xync_client-0.0.7.dev0}/xync_client.egg-info/top_level.txt +0 -0
|
@@ -2,14 +2,12 @@ from asyncio import AbstractEventLoop, get_running_loop
|
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
4
|
import uvloop
|
|
5
|
-
from tortoise import connections
|
|
6
5
|
from tortoise.backends.asyncpg import AsyncpgDBClient
|
|
7
6
|
from x_model import init_db
|
|
8
7
|
from xync_schema import models
|
|
9
8
|
from xync_schema.models import Agent, ExAction, TestEx
|
|
10
9
|
|
|
11
|
-
from xync_client.TgWallet.
|
|
12
|
-
from xync_client.TgWallet.pub import PublicClient
|
|
10
|
+
from xync_client.TgWallet.agent import AgentClient
|
|
13
11
|
from xync_client.loader import DSN
|
|
14
12
|
|
|
15
13
|
|
|
@@ -24,8 +22,7 @@ class TestWallet:
|
|
|
24
22
|
@pytest.fixture(scope="class")
|
|
25
23
|
async def cn(self) -> AsyncpgDBClient:
|
|
26
24
|
TestWallet.loop = get_running_loop()
|
|
27
|
-
await init_db(DSN, models, True)
|
|
28
|
-
cn: AsyncpgDBClient = connections.get("default")
|
|
25
|
+
cn: AsyncpgDBClient = await init_db(DSN, models, True)
|
|
29
26
|
yield cn
|
|
30
27
|
await cn.close()
|
|
31
28
|
|
|
@@ -36,47 +33,15 @@ class TestWallet:
|
|
|
36
33
|
yield tg
|
|
37
34
|
await tg.close()
|
|
38
35
|
|
|
39
|
-
|
|
40
|
-
async def
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
# # 5 - fiats
|
|
47
|
-
# async def test_fiats(self, ac):
|
|
48
|
-
# fiats = await ac.my_fiats()
|
|
49
|
-
# await TestEx.update_or_create({"ok": fiats['status'] == 'SUCCESS'}, ex__name=ac.agent.ex.name, action=ExAction.fiats)
|
|
50
|
-
# assert fiats['status'] == 'SUCCESS', "Failed to get fiats"
|
|
51
|
-
|
|
52
|
-
# 1 - all_curs
|
|
53
|
-
async def test_all_curs(self, pc):
|
|
54
|
-
curs = await pc.curs()
|
|
55
|
-
await TestEx.update_or_create({"ok": bool(curs)}, ex__name="TgWallet", action=ExAction.all_curs_taker)
|
|
56
|
-
assert curs, "No data"
|
|
36
|
+
# 25 - fiats
|
|
37
|
+
async def test_fiats(self, ac):
|
|
38
|
+
fiats = await ac.my_fiats()
|
|
39
|
+
await TestEx.update_or_create(
|
|
40
|
+
{"ok": fiats["status"] == "SUCCESS"}, ex__name=ac.agent.ex.name, action=ExAction.fiats
|
|
41
|
+
)
|
|
42
|
+
assert fiats["status"] == "SUCCESS", "Failed to get fiats"
|
|
57
43
|
|
|
58
|
-
#
|
|
59
|
-
async def test_all_coins(self, pc):
|
|
60
|
-
coins = await pc.coins()
|
|
61
|
-
await TestEx.update_or_create({"ok": bool(coins)}, ex__name="TgWallet", action=ExAction.all_coins)
|
|
62
|
-
assert coins, "No data"
|
|
63
|
-
|
|
64
|
-
# 3 - all_pms
|
|
65
|
-
async def test_all_pms(self, pc):
|
|
66
|
-
pms = await pc.pms()
|
|
67
|
-
await TestEx.update_or_create({"ok": bool(pms)}, ex__name="TgWallet", action=ExAction.all_pms)
|
|
68
|
-
assert pms, "No data"
|
|
69
|
-
|
|
70
|
-
# # 4 - all_ads
|
|
71
|
-
# async def test_cur_filter(self, pc):
|
|
72
|
-
# for cur in 'RUB', 'AZN', 'GEL':
|
|
73
|
-
# for coin in 'TON', 'USDT', 'BTC':
|
|
74
|
-
# for tt in 'SALE', 'PURCHASE':
|
|
75
|
-
# ads = await pc.get_ads(coin, cur, tt)
|
|
76
|
-
# assert len(ads), "No data"
|
|
77
|
-
# await TestEx.update_or_create({"ok": bool(ads)}, ex__name="TgWallet", action=ExAction.all_ads)
|
|
78
|
-
#
|
|
79
|
-
# # 6 - fiat_new
|
|
44
|
+
# # 26 - fiat_new
|
|
80
45
|
# async def test_fiat_new(self, ac):
|
|
81
46
|
# pms = await ac.all_pms()
|
|
82
47
|
# add_pm = await ac.fiat_new(pms[0]['code'], 'RUB', pms[0]['name'], '123456789098765')
|
|
@@ -84,7 +49,7 @@ class TestWallet:
|
|
|
84
49
|
# action=ExAction.fiat_new)
|
|
85
50
|
# assert add_pm['status'] == 'SUCCESS', "Failed to create"
|
|
86
51
|
#
|
|
87
|
-
# #
|
|
52
|
+
# # 27 - fiat_edit
|
|
88
53
|
# async def test_fiat_edit(self, ac):
|
|
89
54
|
# editid = await ac.fiats()
|
|
90
55
|
# pms = await ac.all_pms()
|
|
@@ -93,19 +58,19 @@ class TestWallet:
|
|
|
93
58
|
# action=ExAction.fiat_upd)
|
|
94
59
|
# assert add_pm['status'] == 'SUCCESS', "Failed to edit"
|
|
95
60
|
#
|
|
96
|
-
# #
|
|
61
|
+
# # 28 - fiat_del
|
|
97
62
|
# async def test_fiat_del(self, ac):
|
|
98
63
|
# delid = await ac.fiats()
|
|
99
64
|
# dl = await ac.fiat_del(delid['data'][0]['id'])
|
|
100
65
|
# await TestEx.update_or_create({"ok": dl['status'] == 'SUCCESS'}, ex__name="TgWallet", action=ExAction.fiat_del)
|
|
101
66
|
# assert dl['status'] == "SUCCESS", "Fiat doesn't delete"
|
|
102
67
|
#
|
|
103
|
-
# #
|
|
68
|
+
# # 29 - my_ads
|
|
104
69
|
# async def test_my_ads(self, ac):
|
|
105
70
|
# ads = await ac.my_ads()
|
|
106
71
|
# await TestEx.update_or_create({"ok": ads['status'] == 'SUCCESS'}, ex__name="TgWallet", action=ExAction.my_ads)
|
|
107
72
|
# assert ads['status'] == "SUCCESS", "No data"
|
|
108
|
-
|
|
73
|
+
|
|
109
74
|
# # 10 - ad_new
|
|
110
75
|
# async def test_ad_new(self, ac):
|
|
111
76
|
# fiats = [(await ac.fiats())['data'][0]['id']]
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from asyncio import AbstractEventLoop, get_running_loop
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
import uvloop
|
|
5
|
+
from tortoise.backends.asyncpg import AsyncpgDBClient
|
|
6
|
+
from x_model import init_db
|
|
7
|
+
from xync_schema import models
|
|
8
|
+
from xync_schema.models import Agent, ExAction, TestEx
|
|
9
|
+
|
|
10
|
+
from xync_client.TgWallet.ex import PublicClient
|
|
11
|
+
from xync_client.loader import DSN
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@pytest.mark.asyncio(loop_scope="class")
|
|
15
|
+
class TestWallet:
|
|
16
|
+
loop: AbstractEventLoop
|
|
17
|
+
|
|
18
|
+
@pytest.fixture(scope="class")
|
|
19
|
+
def event_loop_policy(self):
|
|
20
|
+
return uvloop.EventLoopPolicy()
|
|
21
|
+
|
|
22
|
+
@pytest.fixture(scope="class")
|
|
23
|
+
async def cn(self) -> AsyncpgDBClient:
|
|
24
|
+
TestWallet.loop = get_running_loop()
|
|
25
|
+
cn: AsyncpgDBClient = await init_db(DSN, models, True)
|
|
26
|
+
yield cn
|
|
27
|
+
await cn.close()
|
|
28
|
+
|
|
29
|
+
@pytest.fixture(scope="class")
|
|
30
|
+
async def cl(self, cn) -> PublicClient:
|
|
31
|
+
agent = await Agent.get(user_id=1038938370).prefetch_related("ex")
|
|
32
|
+
tg = PublicClient(agent)
|
|
33
|
+
yield tg
|
|
34
|
+
await tg.close()
|
|
35
|
+
|
|
36
|
+
# 20 - all_pms
|
|
37
|
+
async def test_all_pms(self, cl):
|
|
38
|
+
pms = await cl.pms()
|
|
39
|
+
test, _ = await TestEx.update_or_create({"ok": bool(pms)}, ex__name="TgWallet", action=ExAction.pms)
|
|
40
|
+
assert test.ok, "No pms"
|
|
41
|
+
|
|
42
|
+
# 21 - all_curs
|
|
43
|
+
async def test_all_curs(self, cl):
|
|
44
|
+
curs = await cl.curs()
|
|
45
|
+
test, _ = await TestEx.update_or_create({"ok": bool(curs)}, ex__name="TgWallet", action=ExAction.curs)
|
|
46
|
+
assert test.ok, "No curs"
|
|
47
|
+
|
|
48
|
+
# 22 - all_pms
|
|
49
|
+
async def test_cur_pms_map(self, cl):
|
|
50
|
+
pms = await cl.cur_pms_map()
|
|
51
|
+
test, _ = await TestEx.update_or_create({"ok": bool(pms)}, ex__name="TgWallet", action=ExAction.pms)
|
|
52
|
+
assert test.ok, "No pms"
|
|
53
|
+
|
|
54
|
+
# 23 - all_coins
|
|
55
|
+
async def test_all_coins(self, cl):
|
|
56
|
+
coins = await cl.coins()
|
|
57
|
+
test, _ = await TestEx.update_or_create({"ok": bool(coins)}, ex__name="TgWallet", action=ExAction.coins)
|
|
58
|
+
assert test.ok, "No coins"
|
|
59
|
+
|
|
60
|
+
# 24 - all_ads
|
|
61
|
+
async def test_cur_filter(self, cl):
|
|
62
|
+
for cur in "RUB", "AZN", "GEL":
|
|
63
|
+
for coin in "TON", "USDT", "BTC":
|
|
64
|
+
for tt in True, False:
|
|
65
|
+
ads = await cl.ads(coin, cur, tt)
|
|
66
|
+
assert len(ads), "No data"
|
|
67
|
+
await TestEx.update_or_create({"ok": bool(ads)}, ex__name="TgWallet", action=ExAction.ads)
|
|
@@ -4,7 +4,8 @@ from abc import abstractmethod
|
|
|
4
4
|
from aiohttp import ClientResponse
|
|
5
5
|
from aiohttp.http_exceptions import HttpProcessingError
|
|
6
6
|
from x_client.aiohttp import Client
|
|
7
|
-
from xync_schema.
|
|
7
|
+
from xync_schema.enums import PmType
|
|
8
|
+
from xync_schema.models import Agent, Ex, User, OrderStatus, Coin, Cur, Order, Pm, Ad, AdStatus, Fiat
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
class AgentClient(Client):
|
|
@@ -116,17 +116,21 @@ class ExClient(Client):
|
|
|
116
116
|
norm = self._pmnorm(pm["name"])
|
|
117
117
|
if prev[1:] == (norm, pm["name"]):
|
|
118
118
|
logging.warning(f"Pm: '{pm['name']}' duplicated with ids {prev[0]}:{k} on {self.ex.name}")
|
|
119
|
-
await Pmex.update_or_create(
|
|
119
|
+
await Pmex.update_or_create(
|
|
120
|
+
{"pm": pms.get(prev[0], await Pm.get(name=prev[2]))}, ex=self.ex, exid=k, name=pm["name"]
|
|
121
|
+
)
|
|
120
122
|
elif prev[1] == norm:
|
|
121
123
|
logging.error(
|
|
122
124
|
f"Pm: '{pm['name']}' and '{prev[2]}' overnormed as '{norm}' with ids {prev[0]}:{k} on {self.ex.name}"
|
|
123
125
|
)
|
|
124
|
-
await Pmex.update_or_create(
|
|
126
|
+
await Pmex.update_or_create(
|
|
127
|
+
{"pm": pms.get(prev[0], await Pm.get(name=prev[2]))}, ex=self.ex, exid=k, name=pm["name"]
|
|
128
|
+
)
|
|
125
129
|
else:
|
|
126
130
|
pms[k], _ = await Pm.update_or_create(**pm, identifier=norm)
|
|
127
131
|
prev = k, norm, pm["name"]
|
|
128
132
|
# Pmexs
|
|
129
|
-
pmexs = [Pmex(exid=k, ex=self.ex, pm=pm) for k, pm in pms.items()]
|
|
133
|
+
pmexs = [Pmex(exid=k, ex=self.ex, pm=pm, name=pm.name) for k, pm in pms.items()]
|
|
130
134
|
await Pmex.bulk_create(pmexs, ignore_conflicts=True)
|
|
131
135
|
# Curs
|
|
132
136
|
cursd = await self.curs()
|
xync_client-0.0.3/xync_client/Binance/web.py → xync_client-0.0.7.dev0/xync_client/Binance/ex.py
RENAMED
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
from asyncio import run
|
|
2
2
|
|
|
3
3
|
from x_model import init_db
|
|
4
|
+
from xync_schema.enums import PmType
|
|
4
5
|
|
|
5
6
|
from xync_client.Abc.Ex import ExClient
|
|
6
|
-
from xync_client.
|
|
7
|
+
from xync_client.Binance.sapi import Sapi
|
|
8
|
+
from xync_client.loader import DSN, BKEY, BSEC
|
|
7
9
|
from xync_schema import models
|
|
8
10
|
from xync_schema.models import Ex
|
|
9
11
|
|
|
10
12
|
|
|
11
|
-
class
|
|
13
|
+
class Client(ExClient):
|
|
14
|
+
def __init__(self, ex: Ex, bkeys):
|
|
15
|
+
self.sapi = Sapi(*bkeys)
|
|
16
|
+
super().__init__(ex)
|
|
17
|
+
|
|
12
18
|
async def curs(self) -> dict:
|
|
13
19
|
curs = await self._post("/bapi/c2c/v1/friendly/c2c/trade-rule/fiat-list")
|
|
14
20
|
return {c["currencyCode"]: c["countryCode"] for c in curs["data"]}
|
|
@@ -16,13 +22,22 @@ class Public(ExClient):
|
|
|
16
22
|
async def coins(self) -> list[dict]:
|
|
17
23
|
pass
|
|
18
24
|
|
|
19
|
-
async def pms(self) ->
|
|
20
|
-
|
|
25
|
+
async def pms(self) -> dict[str, dict]:
|
|
26
|
+
pms = await self.sapi.get_pay_meths()
|
|
27
|
+
return {
|
|
28
|
+
pm["id"]: {
|
|
29
|
+
"name": pm["name"],
|
|
30
|
+
"identifier": pm["identifier"],
|
|
31
|
+
"type_": PmType[pm["typeCode"].replace("-", "_")].value,
|
|
32
|
+
"logo": pm["iconUrlColor"],
|
|
33
|
+
}
|
|
34
|
+
for pm in pms["data"]
|
|
35
|
+
}
|
|
21
36
|
|
|
22
37
|
# 22: Cur -> [Pm] rels
|
|
23
38
|
async def cur_pms_map(self) -> dict[int, set[int]]: # {cur.exid: [pm.exid], [pm.exid]}
|
|
24
39
|
res = await self.curs()
|
|
25
|
-
mp = {c: await self.
|
|
40
|
+
mp = {c: await self._get_pms_for_cur(c) for c in res.keys()}
|
|
26
41
|
return mp
|
|
27
42
|
|
|
28
43
|
# # 22: Cur -> [Pm] rels
|
|
@@ -34,12 +49,13 @@ class Public(ExClient):
|
|
|
34
49
|
async def ads(self, coin_exid: str, cur_exid: str, is_sell: bool, pm_exids: list[str] = None) -> list[dict]:
|
|
35
50
|
pass
|
|
36
51
|
|
|
37
|
-
async def
|
|
52
|
+
async def _get_pms_for_cur(self, cur: str) -> ([str], [str]):
|
|
38
53
|
data = {"fiat": cur, "classifies": ["mass", "profession"]}
|
|
39
54
|
res = await self._post("/bapi/c2c/v2/public/c2c/adv/filter-conditions", data)
|
|
40
|
-
return [
|
|
41
|
-
|
|
42
|
-
]
|
|
55
|
+
return [r["identifier"] for r in res["data"]["tradeMethods"]]
|
|
56
|
+
# , [
|
|
57
|
+
# r["scode"] for r in res["data"]["countries"] if r["scode"] != "ALL"
|
|
58
|
+
# ] # countries,tradeMethods,periods
|
|
43
59
|
|
|
44
60
|
|
|
45
61
|
# class Private(Public): # todo: base class: Public or Client?
|
|
@@ -61,8 +77,8 @@ class Public(ExClient):
|
|
|
61
77
|
async def main():
|
|
62
78
|
_ = await init_db(DSN, models, True)
|
|
63
79
|
ex = await Ex.get(name="Binance")
|
|
64
|
-
cl =
|
|
65
|
-
await cl.
|
|
80
|
+
cl = Client(ex, (BKEY, BSEC))
|
|
81
|
+
await cl.set_pmcurexs()
|
|
66
82
|
await cl.close()
|
|
67
83
|
|
|
68
84
|
|
|
@@ -136,7 +136,7 @@ class Sapi(Client):
|
|
|
136
136
|
# "userTradeVolumeMin": 0,
|
|
137
137
|
# "yubikeyVerifyCode": "string"
|
|
138
138
|
}
|
|
139
|
-
return await self._post(Ep.
|
|
139
|
+
return await self._post(Ep.POST_AD, body)
|
|
140
140
|
|
|
141
141
|
# 6. Search Ads
|
|
142
142
|
async def search_ads(self, asset, fiat, trade_type, pms: [str] = None, amount: int = None, page=1, rows=20):
|
|
@@ -31,7 +31,7 @@ class Client(ExClient):
|
|
|
31
31
|
# 22: Список платежных методов по каждой валюте
|
|
32
32
|
async def cur_pms_map(self) -> dict[int, set[int]]:
|
|
33
33
|
res = await self._coin_curs_pms()
|
|
34
|
-
wrong_pms = {4, 34,
|
|
34
|
+
wrong_pms = {4, 34, 498, 548, 20009, 20010} # , 212, 239, 363 # these ids not exist in pms
|
|
35
35
|
return {c["currencyId"]: set(c["supportPayments"]) - wrong_pms for c in res["currency"] if c["supportPayments"]}
|
|
36
36
|
|
|
37
37
|
async def coins(self) -> dict[int, str]:
|
|
@@ -2,10 +2,10 @@ from enum import StrEnum, IntEnum
|
|
|
2
2
|
from typing import Literal
|
|
3
3
|
|
|
4
4
|
from x_client.http import Client
|
|
5
|
-
from xync_schema.models import User, Cur,
|
|
6
|
-
from xync_schema.pydantic import
|
|
5
|
+
from xync_schema.models import User, Cur, Order, Coin, OrderStatus, Pmex
|
|
6
|
+
from xync_schema.pydantic import FiatNew
|
|
7
7
|
|
|
8
|
-
from xync_client.Abc import AgentClient as BaseClient
|
|
8
|
+
from xync_client.Abc.Agent import AgentClient as BaseClient
|
|
9
9
|
from xync_client.TgWallet.pyro import PyroClient
|
|
10
10
|
|
|
11
11
|
|
|
@@ -38,13 +38,12 @@ class AgentClient(BaseClient):
|
|
|
38
38
|
|
|
39
39
|
async def order_request(self, ad_id: int, amount: float) -> Order: ...
|
|
40
40
|
|
|
41
|
-
async def my_fiats(self, cur: Cur = None) ->
|
|
41
|
+
async def my_fiats(self, cur: Cur = None) -> dict:
|
|
42
42
|
fiats = await self._post("/p2p/public-api/v3/payment-details/get/by-user-id")
|
|
43
|
-
for fiat in fiats["data"]
|
|
44
|
-
|
|
45
|
-
fiats = [await Fiat()]
|
|
43
|
+
fiats = {fiat["id"]: fiat for fiat in fiats["data"]}
|
|
44
|
+
return fiats
|
|
46
45
|
|
|
47
|
-
async def fiat_new(self, fiat:
|
|
46
|
+
async def fiat_new(self, fiat: FiatNew):
|
|
48
47
|
pmex = await Pmex.get(pm_id=fiat.pm_id, ex=self.agent.ex) # .prefetch_related('pm')
|
|
49
48
|
cur = await Cur[fiat.cur_id]
|
|
50
49
|
add_fiat = await self._post(
|
|
@@ -0,0 +1,78 @@
|
|
|
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
|
|
@@ -5,13 +5,8 @@ README.md
|
|
|
5
5
|
makefile
|
|
6
6
|
pyproject.toml
|
|
7
7
|
tests/__init__.py
|
|
8
|
-
tests/
|
|
9
|
-
tests/
|
|
10
|
-
tests/test_bybit.py
|
|
11
|
-
tests/test_bybit_p2p.py
|
|
12
|
-
tests/test_gate.py
|
|
13
|
-
tests/test_htx_p2p.py
|
|
14
|
-
tests/test_wallet.py
|
|
8
|
+
tests/wallet/test_agent.py
|
|
9
|
+
tests/wallet/test_ex.py
|
|
15
10
|
xync_client/__init__.py
|
|
16
11
|
xync_client/loader.py
|
|
17
12
|
xync_client.egg-info/PKG-INFO
|
|
@@ -24,9 +19,9 @@ xync_client/Abc/Ex.py
|
|
|
24
19
|
xync_client/Abc/Order.py
|
|
25
20
|
xync_client/Binance/binance_async.py
|
|
26
21
|
xync_client/Binance/earn_api.py
|
|
22
|
+
xync_client/Binance/ex.py
|
|
27
23
|
xync_client/Binance/exceptions.py
|
|
28
24
|
xync_client/Binance/sapi.py
|
|
29
|
-
xync_client/Binance/web.py
|
|
30
25
|
xync_client/Binance/web_c2c.py
|
|
31
26
|
xync_client/BitGet/pub.py
|
|
32
27
|
xync_client/Bybit/web_earn.py
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
from x_model import init_db
|
|
2
|
-
from xync_client.loader import DSN
|
|
3
|
-
from xync_schema import models
|
|
4
|
-
from xync_schema.models import Ex
|
|
5
|
-
|
|
6
|
-
from xync_client.Binance.web import Public
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
async def test_cur_filter():
|
|
10
|
-
_ = await init_db(DSN, models, True)
|
|
11
|
-
ex = await Ex.get(name="Binance")
|
|
12
|
-
bn = Public(ex)
|
|
13
|
-
resp = await bn.cur_pms_map()
|
|
14
|
-
assert len(resp[0]) and len(resp[1]), "No data"
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
from datetime import datetime
|
|
2
|
-
from uuid import uuid4
|
|
3
|
-
from pybit.unified_trading import HTTP
|
|
4
|
-
|
|
5
|
-
from xync_client.Bybit.web_earn import BybitEarn, type_map
|
|
6
|
-
from xync_client.loader import BYT, BYKEY, BYSEC
|
|
7
|
-
|
|
8
|
-
client = HTTP(
|
|
9
|
-
testnet=False,
|
|
10
|
-
api_key=BYKEY,
|
|
11
|
-
api_secret=BYSEC,
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
async def test_get_home_products():
|
|
16
|
-
bbt = BybitEarn(BYT)
|
|
17
|
-
for pt in type_map:
|
|
18
|
-
resp = await bbt.get_home_earn_products(pt.value)
|
|
19
|
-
assert len(resp[pt.name]), "No home products"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
async def test_get_coins():
|
|
23
|
-
bbt = BybitEarn(BYT)
|
|
24
|
-
resp = await bbt.get_coins()
|
|
25
|
-
assert resp, "No coins"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
async def test_get_eth():
|
|
29
|
-
bbt = BybitEarn(BYT)
|
|
30
|
-
resp = await bbt.get_product_detail()
|
|
31
|
-
assert resp, "No eth"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def test_get_rate():
|
|
35
|
-
resp = client.get_tickers(category="spot", symbol="TONUSDT")
|
|
36
|
-
assert float(resp["result"]["list"][0]["lastPrice"]) > 0
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def test_send_coin_internal():
|
|
40
|
-
coin = "USDT"
|
|
41
|
-
old_sender_balance = client.get_coins_balance(
|
|
42
|
-
accountType="FUND",
|
|
43
|
-
coin=coin,
|
|
44
|
-
)["result"]["balance"][0]
|
|
45
|
-
# sender_id = 23477628
|
|
46
|
-
# receiver_id = 138687729
|
|
47
|
-
receiver_id = 69798104
|
|
48
|
-
sent_amount = 24.9266
|
|
49
|
-
assert float(old_sender_balance["transferBalance"]) >= sent_amount, "sender have not enough money"
|
|
50
|
-
|
|
51
|
-
trans_sent_id = client.withdraw(
|
|
52
|
-
coin=coin,
|
|
53
|
-
# chain=None,
|
|
54
|
-
address=str(receiver_id),
|
|
55
|
-
amount=str(sent_amount),
|
|
56
|
-
timestamp=int(datetime.now().timestamp() * 1000),
|
|
57
|
-
forceChain=2,
|
|
58
|
-
accountType="FUND",
|
|
59
|
-
)["result"]
|
|
60
|
-
new_sender_balance = client.get_coins_balance(
|
|
61
|
-
accountType="FUND",
|
|
62
|
-
coin=coin,
|
|
63
|
-
)["result"]["balance"][0]
|
|
64
|
-
assert (
|
|
65
|
-
trans_sent_id
|
|
66
|
-
and float(new_sender_balance["walletBalance"]) == float(old_sender_balance["walletBalance"]) - sent_amount
|
|
67
|
-
), "transfer failed"
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def test_send_coin_subaccount():
|
|
71
|
-
sender_id = 23477628
|
|
72
|
-
receiver_id = 69798104
|
|
73
|
-
sent_amount = 15.5
|
|
74
|
-
sent = client.create_universal_transfer( # its only for subaccount transfers
|
|
75
|
-
transferId=str(uuid4()),
|
|
76
|
-
coin="USDT",
|
|
77
|
-
amount=str(sent_amount),
|
|
78
|
-
fromMemberId=sender_id,
|
|
79
|
-
toMemberId=receiver_id,
|
|
80
|
-
fromAccountType="FUND",
|
|
81
|
-
toAccountType="FUND",
|
|
82
|
-
)["result"]
|
|
83
|
-
assert sent, "transfer failed"
|
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
from time import sleep
|
|
2
|
-
|
|
3
|
-
import pytest
|
|
4
|
-
from tortoise import Tortoise, connections
|
|
5
|
-
from tortoise.backends.asyncpg import AsyncpgDBClient
|
|
6
|
-
from xync_schema import models
|
|
7
|
-
from xync_schema.models import TestEx, ExAction, Pmcur
|
|
8
|
-
|
|
9
|
-
from xync_client.Bybit.web_p2p import BybitP2P, NoMakerException, AdsStatus
|
|
10
|
-
from xync_client.loader import BYTP2P, DSN
|
|
11
|
-
|
|
12
|
-
bybit_p2p = BybitP2P(headers={"cookie": "secure-token=" + BYTP2P})
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@pytest.fixture(scope="module")
|
|
16
|
-
async def dbc() -> AsyncpgDBClient:
|
|
17
|
-
await Tortoise.init(db_url=DSN, modules={"models": [models]})
|
|
18
|
-
cn: AsyncpgDBClient = connections.get("default")
|
|
19
|
-
yield cn
|
|
20
|
-
await cn.close()
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
# получение валют (1)
|
|
24
|
-
async def test_get_currencies(dbc):
|
|
25
|
-
currencies = bybit_p2p.get_currencies()
|
|
26
|
-
Pmcur.update_or_create(
|
|
27
|
-
{},
|
|
28
|
-
)
|
|
29
|
-
ok = True if len(currencies) > 0 else False
|
|
30
|
-
await TestEx.update_or_create({"ok": ok}, ex_id=10, action=ExAction.all_curs_taker)
|
|
31
|
-
assert ok, "No currencies found"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
# получение не тестовых монет торгуемых на p2p (2)
|
|
35
|
-
async def test_get_coins(dbc):
|
|
36
|
-
result_get_coins = bybit_p2p.get_coins()
|
|
37
|
-
ok = (
|
|
38
|
-
True
|
|
39
|
-
if len([c for c in result_get_coins["result"] if c["tokenType"] == "CHAIN_TOKEN" and not c["isTest"]]) > 0
|
|
40
|
-
else False
|
|
41
|
-
)
|
|
42
|
-
await TestEx.update_or_create({"ok": ok}, ex_id=10, action=ExAction.all_coins)
|
|
43
|
-
assert ok, "No coins found"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
# получение платежных методов (3)
|
|
47
|
-
async def test_get_payment_methods(dbc):
|
|
48
|
-
result_get_payment_methods = bybit_p2p.get_payment_methods()
|
|
49
|
-
ok = True if len(result_get_payment_methods["result"]["paymentConfigVo"]) > 0 else False
|
|
50
|
-
await TestEx.update_or_create({"ok": ok}, ex_id=10, action=ExAction.all_pms)
|
|
51
|
-
assert ok, "No payment method found"
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
# получение первого объявления на покупку USDT за рубли (покупка - "side": "1", продажа - "side": "0") (4)
|
|
55
|
-
async def test_get_best_price(dbc):
|
|
56
|
-
all_ads = bybit_p2p.get_ads("USDT", "RUB")
|
|
57
|
-
ok1 = True if bybit_p2p.get_rate(all_ads) > 0 else False # "Ad's price USDT/RUB no found no Payeer, no Advcash"
|
|
58
|
-
ok2 = True if len(all_ads) > 0 else False
|
|
59
|
-
await TestEx.update_or_create({"ok": ok1 and ok2}, ex_id=10, action=ExAction.all_ads)
|
|
60
|
-
assert ok2, "Ad's price USDT/RUB no found"
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
# получение платежных методов залогиненного юзера (5)
|
|
64
|
-
async def test_get_user_pay_methods(dbc):
|
|
65
|
-
result_get_user_pay_methods = bybit_p2p.get_user_pay_methods()
|
|
66
|
-
ok = True if len(result_get_user_pay_methods) > 0 else False
|
|
67
|
-
await TestEx.update_or_create({"ok": ok}, ex_id=10, action=ExAction.fiats)
|
|
68
|
-
assert ok, "No payment method requisites found"
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
# создание моего платежного реквизита (fiat) (6)
|
|
72
|
-
async def test_create_user_payment_methods(dbc):
|
|
73
|
-
result = bybit_p2p.create_payment_method(379, "ЕЛЕНА АРТЕМЬЕВА", "42454342536453")
|
|
74
|
-
ok = True if result["ret_msg"] == "SUCCESS" else False
|
|
75
|
-
await TestEx.update_or_create({"ok": ok}, ex_id=10, action=ExAction.fiat_new)
|
|
76
|
-
assert ok, "Fiat isn't created: " + result["ret_msg"]
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
# редактирование моего платежного реквизита (fiat) (7)
|
|
80
|
-
async def test_update_user_payment_methods(dbc):
|
|
81
|
-
result = bybit_p2p.update_payment_method("ЕЛЕНА АРТЕМЬЕВА", "424543425364532")
|
|
82
|
-
if result["ret_msg"] != "SUCCESS":
|
|
83
|
-
print("Wrong 2fa on Fiat updating, wait 10 secs and retry..")
|
|
84
|
-
sleep(10)
|
|
85
|
-
return await test_update_user_payment_methods(dbc)
|
|
86
|
-
await TestEx.update_or_create({"ok": True}, ex_id=10, action=ExAction.fiat_upd)
|
|
87
|
-
assert True, "Fiat isn't updated: " + result["ret_msg"]
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
# удаление моего платежного реквизита (fiat) (8)
|
|
91
|
-
async def test_delete_user_payment_methods(dbc):
|
|
92
|
-
last_fiat = bybit_p2p.get_payment_method()
|
|
93
|
-
result = bybit_p2p.delete_payment_method(last_fiat["id"])
|
|
94
|
-
if result["ret_msg"] != "SUCCESS":
|
|
95
|
-
print("Wrong 2fa on Fiat deleting, wait 10 secs and retry..")
|
|
96
|
-
sleep(10)
|
|
97
|
-
return await test_delete_user_payment_methods(dbc)
|
|
98
|
-
await TestEx.update_or_create({"ok": True}, ex_id=10, action=ExAction.fiat_del)
|
|
99
|
-
assert True, "Fiat isn't deleted: " + result["ret_msg"]
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
# получение списка объявлений залогиненного юзера (9)
|
|
103
|
-
async def test_get_user_ads(dbc):
|
|
104
|
-
result_get_user_ads = bybit_p2p.get_user_ads()
|
|
105
|
-
ok = True if len(result_get_user_ads) >= 0 else False
|
|
106
|
-
await TestEx.update_or_create({"ok": ok}, ex_id=10, action=ExAction.my_ads)
|
|
107
|
-
assert ok, "No ads found"
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
# создание/редактирование/удаление объявления (10,11,12)
|
|
111
|
-
async def test_delete_ad(dbc):
|
|
112
|
-
try:
|
|
113
|
-
token = bybit_p2p.get_security_token_create()
|
|
114
|
-
bybit_p2p.post_create_ad(token)
|
|
115
|
-
token = bybit_p2p.get_security_token_update()
|
|
116
|
-
bybit_p2p.post_update_ad(token)
|
|
117
|
-
result_delete_ad = bybit_p2p.delete_ad(bybit_p2p.last_ad_id[0])
|
|
118
|
-
except NoMakerException as e:
|
|
119
|
-
print(e.args[0]["ret_msg"])
|
|
120
|
-
result_delete_ad = e.args[0]
|
|
121
|
-
ok = True if result_delete_ad["ret_msg"] == "SUCCESS" else False
|
|
122
|
-
await TestEx.update_or_create({"ok": ok}, ex_id=10, action=ExAction.ad_new)
|
|
123
|
-
await TestEx.update_or_create({"ok": ok}, ex_id=10, action=ExAction.ad_upd)
|
|
124
|
-
await TestEx.update_or_create({"ok": ok}, ex_id=10, action=ExAction.ad_del)
|
|
125
|
-
assert ok, "Ad isn't deleted"
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
async def _switch_ad(new_status: AdsStatus, dbc):
|
|
129
|
-
result = bybit_p2p.switch_ads(new_status)
|
|
130
|
-
ok = True if result["ret_msg"] == "SUCCESS" else False
|
|
131
|
-
action = {AdsStatus.REST: ExAction.ad_off, AdsStatus.WORKING: ExAction.ad_on}[new_status]
|
|
132
|
-
await TestEx.update_or_create({"ok": ok}, ex_id=10, action=action)
|
|
133
|
-
return ok
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
# выключение/включение объявления (13,14)
|
|
137
|
-
async def test_on_off_ads(dbc):
|
|
138
|
-
old_status = AdsStatus[bybit_p2p.online_ads()]
|
|
139
|
-
new_status = AdsStatus(int(not bool(old_status.name)))
|
|
140
|
-
ok = await _switch_ad(new_status, dbc)
|
|
141
|
-
assert ok, "Ads no " + new_status.name
|
|
142
|
-
# возвращаем как было:
|
|
143
|
-
ok = await _switch_ad(old_status, dbc)
|
|
144
|
-
assert ok, "Ads no " + old_status.name
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
# старт заявки (тейкером 17)
|
|
148
|
-
async def test_create_order_taker():
|
|
149
|
-
ads = bybit_p2p.get_ads("USDT", "RUB", payment=["51"])
|
|
150
|
-
ad = ads[0]
|
|
151
|
-
# get_order_info = bybit_p2p.get_order_info(ad["id"])
|
|
152
|
-
result = bybit_p2p.create_order_taker(
|
|
153
|
-
ad["id"], "USDT", "RUB", False, ad["minAmount"], float(ad["minAmount"]) / float(ad["price"]), ad["price"]
|
|
154
|
-
)
|
|
155
|
-
ok = True if result["ret_msg"] == "SUCCESS" else False
|
|
156
|
-
await TestEx.update_or_create({"ok": ok}, ex_id=10, action=ExAction.take_ad)
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
# сообщения чата (тейкером 21)
|
|
160
|
-
async def test_get_chat_msgs(dbc):
|
|
161
|
-
msgs = bybit_p2p.get_chat_msg("1832490804709646336")
|
|
162
|
-
assert len(msgs) > 0, "No have msgs"
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
async def test_user_block(dbc):
|
|
166
|
-
bu = bybit_p2p.block_user("146246740")
|
|
167
|
-
assert bu["result"], "User don't block"
|
|
168
|
-
ubu = bybit_p2p.unblock_user("146246740")
|
|
169
|
-
assert ubu["result"], "User don't unblock"
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
# поставить отзыв (27)
|
|
173
|
-
async def test_user_review_post(dbc):
|
|
174
|
-
result = bybit_p2p.user_review_post("1831422797854318592")
|
|
175
|
-
assert result["ret_msg"] == "SUCCESS", "Review post failed"
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
# получшение заявок по всем ордерам за заданное время, статус, направление, монета (32)
|
|
179
|
-
async def test_get_orders_done(dbc):
|
|
180
|
-
result = bybit_p2p.get_orders_done(1717189200000, 1722545999999, 50, 1, "USDT")
|
|
181
|
-
assert result["ret_msg"] == "SUCCESS", "No orders done"
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
# получшение заявок по активным ордерам за заданное время, статус, направление, монета (32)
|
|
185
|
-
async def test_get_orders_active(dbc):
|
|
186
|
-
result = bybit_p2p.get_orders_active(1717189200000, 1722545999999, 50, 1, "USDT")
|
|
187
|
-
assert result["ret_msg"] == "SUCCESS", "No active orders"
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
# 33
|
|
191
|
-
async def test_get_order_info(dbc):
|
|
192
|
-
get_order_info = bybit_p2p.get_order_info("1819108572048125952")
|
|
193
|
-
assert get_order_info, "No order info"
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
from xync_client.Gate.premarket import Priv
|
|
2
|
-
from xync_client.loader import GATE_UID, GATE_PVER
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
async def test_get_premarket_ads():
|
|
6
|
-
gate = Priv(GATE_UID, GATE_PVER)
|
|
7
|
-
resp = await gate.get_premarket_ads()
|
|
8
|
-
assert len(resp), "No premarket ads"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
async def test_get_my_premarket_ads():
|
|
12
|
-
gate = Priv(GATE_UID, GATE_PVER)
|
|
13
|
-
resp = await gate.get_my_premarket_ads()
|
|
14
|
-
assert len(resp), "No my premarket ads"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
async def test_create_premarket_ad():
|
|
18
|
-
gate = Priv(GATE_UID, GATE_PVER)
|
|
19
|
-
resp = await gate.post_premarket_ad(0.649, 5)
|
|
20
|
-
assert resp, "Premarket ad not created"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
async def test_delate_premarket_ad():
|
|
24
|
-
gate = Priv(GATE_UID, GATE_PVER)
|
|
25
|
-
resp = await gate.del_premarket_ad(62089)
|
|
26
|
-
assert resp, "Premarket ad not delated"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
async def test_set_premarket_ads():
|
|
30
|
-
gate = Priv(GATE_UID, GATE_PVER)
|
|
31
|
-
my_ads = await gate.get_my_premarket_ads()
|
|
32
|
-
my_ids = [ad["order_id"] for ad in my_ads]
|
|
33
|
-
resp = await gate.get_premarket_ads()
|
|
34
|
-
for ad in resp:
|
|
35
|
-
if ad["order_id"] in my_ids:
|
|
36
|
-
pass
|
|
37
|
-
|
|
38
|
-
assert len(resp), "No premarket ads"
|
|
File without changes
|
|
@@ -1,101 +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 Coin, Cur, Pm, Ad, Curex, Agent, Ex
|
|
7
|
-
|
|
8
|
-
from xync_client.Abc import PublicClient as BasePublicClient
|
|
9
|
-
from xync_client.TgWallet.pyro import PyroClient
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class PublicClient(BasePublicClient):
|
|
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) -> list[str]:
|
|
47
|
-
coins_curs = await self._post("/p2p/public-api/v2/currency/all-supported")
|
|
48
|
-
return [c["code"] for c in coins_curs["data"]["fiat"]]
|
|
49
|
-
|
|
50
|
-
async def curs(self) -> list[Cur.pyd_list_item()]:
|
|
51
|
-
curs = [(await Cur.update_or_create(ticker=c))[0] for c in await self._curs()]
|
|
52
|
-
[await Curex.update_or_create(cur=c, ex=self.agent.ex) for c in curs] # add curexs
|
|
53
|
-
return [Cur.pyd_list_item().model_validate(c, from_attributes=True) for c in curs]
|
|
54
|
-
|
|
55
|
-
async def _coins(self) -> list[str]:
|
|
56
|
-
coins_curs = await self._post("/p2p/public-api/v2/currency/all-supported")
|
|
57
|
-
return [c["code"] for c in coins_curs["data"]["crypto"]]
|
|
58
|
-
|
|
59
|
-
async def coins(self, cur: Cur = None) -> list[Coin.pyd_list_item()]:
|
|
60
|
-
coins = [(await Coin.update_or_create(ticker=c))[0] for c in await self._coins()]
|
|
61
|
-
[await Curex.update_or_create(coin=c, ex=self.agent.ex) for c in coins] # add coinexs
|
|
62
|
-
return [Coin.pyd_list_item().model_validate(c, from_attributes=True) for c in coins]
|
|
63
|
-
|
|
64
|
-
async def _pms(self, cur: str = "RUB") -> list[Pm]:
|
|
65
|
-
pms = await self._post("/p2p/public-api/v3/payment-details/get-methods/by-currency-code", {"currencyCode": cur})
|
|
66
|
-
return pms["data"]
|
|
67
|
-
|
|
68
|
-
async def pms(self, cur: str = "RUB") -> list[Pm]:
|
|
69
|
-
# get from api
|
|
70
|
-
pmcurs = {cur: await self._pms(cur) for cur in await self._curs()}
|
|
71
|
-
pp = {}
|
|
72
|
-
[[pp.update({p["code"]: p["nameEng"]}) for p in ps] for ps in pmcurs.values()]
|
|
73
|
-
pp = {k: v for k, v in sorted(pp.items(), key=lambda x: x[0])}
|
|
74
|
-
return pp
|
|
75
|
-
# pms_new = await self._post(
|
|
76
|
-
# "/p2p/public-api/v3/payment-details/get-methods/by-currency-code", {"currencyCode": cur}
|
|
77
|
-
# )
|
|
78
|
-
# pms_new_idfs: dict[str, str] = {
|
|
79
|
-
# pn["code"]: pn["nameEng"].lower().replace(" ", "").replace("-", "") for pn in pms_new["data"]
|
|
80
|
-
# }
|
|
81
|
-
# pms_new_names = {name: idf for idf, name in pms_new_idfs.items()}
|
|
82
|
-
# # prepare old payMeths
|
|
83
|
-
# pms_old = await Pm.all()
|
|
84
|
-
# pms_old_idfs: dict[str, Pm] = {
|
|
85
|
-
# pm.identifier.lower().replace(" ", "").replace("-", ""): pm for pm in pms_old if pm.identifier
|
|
86
|
-
# }
|
|
87
|
-
# pms_old_names: dict[str, Pm] = {
|
|
88
|
-
# pm.name.lower().replace(" ", "").replace("-", ""): pm for pm in pms_old if pm.name
|
|
89
|
-
# }
|
|
90
|
-
|
|
91
|
-
async def ads(self, coin: Coin, cur: Cur, is_sell: bool, pms: list[Pm] = None) -> list[Ad.pyd_list_item()]:
|
|
92
|
-
params = {
|
|
93
|
-
"baseCurrencyCode": coin,
|
|
94
|
-
"quoteCurrencyCode": cur,
|
|
95
|
-
"offerType": is_sell,
|
|
96
|
-
"offset": 0,
|
|
97
|
-
"limit": 100,
|
|
98
|
-
# ,"merchantVerified":"TRUSTED"
|
|
99
|
-
}
|
|
100
|
-
ads = await self._post("/p2p/public-api/v2/offer/depth-of-market/", params)
|
|
101
|
-
return ads
|
|
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
|
|
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
|