xync-client 0.0.93.dev29__tar.gz → 0.0.95.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.93.dev29/xync_client.egg-info → xync_client-0.0.95.dev0}/PKG-INFO +1 -1
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/tests/TestAgent.py +3 -3
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/tests/TestEx.py +5 -5
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Abc/Agent.py +1 -1
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Abc/Ex.py +23 -25
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Abc/PmAgent.py +12 -5
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Abc/xtype.py +2 -2
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BingX/agent.py +23 -20
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Bybit/InAgent.py +77 -40
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Bybit/agent.py +20 -20
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Htx/agent.py +3 -3
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Htx/ex.py +1 -1
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Payeer/__init__.py +56 -33
- xync_client-0.0.95.dev0/xync_client/Pms/Payeer/login.py +45 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Volet/__init__.py +2 -2
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Xync/__main__.py +28 -138
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/TgWallet/agent.py +15 -15
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/TgWallet/ex.py +2 -2
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/TgWallet/inAgent.py +3 -5
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/pm_unifier.py +3 -3
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0/xync_client.egg-info}/PKG-INFO +1 -1
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client.egg-info/SOURCES.txt +0 -1
- xync_client-0.0.93.dev29/index.html +0 -397
- xync_client-0.0.93.dev29/xync_client/Pms/Payeer/login.py +0 -33
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/.env.sample +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/.gitignore +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/.pre-commit-config.yaml +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/README.md +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/__init__.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/makefile +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/pyproject.toml +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/setup.cfg +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/tests/TestAsset.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/tests/TestOrder.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/tests/_todo_refact/Binance/test_binance.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/tests/_todo_refact/Bybit/test_bybit.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/tests/_todo_refact/Bybit/test_bybit_p2p.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/tests/_todo_refact/Gate/test_gate.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/tests/_todo_refact/Wallet/test_agent.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/tests/_todo_refact/Wallet/test_ex.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/tests/_todo_refact/__init__.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/tests/_todo_refact/_test_ex.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Abc/Asset.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Abc/Auth.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Abc/BaseTest.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Abc/Exception.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Abc/InAgent.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Abc/Order.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Binance/__init__.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Binance/binance_async.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Binance/earn_api.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Binance/etype/ad.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Binance/etype/pm.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Binance/ex.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Binance/exceptions.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Binance/sapi.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Binance/web_c2c.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BingX/__init__.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BingX/base.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BingX/etype/ad.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BingX/etype/pm.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BingX/ex.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BingX/req.mjs +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BingX/sign.js +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BitGet/__init__.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BitGet/agent.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BitGet/etype/ad.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BitGet/ex.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BitPapa/ex.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Bybit/etype/ad.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Bybit/etype/cred.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Bybit/etype/order.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Bybit/ex.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Bybit/order.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Bybit/web_earn.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Bybit/web_p2p.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Bybit/ws.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Gate/etype/ad.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Gate/ex.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Gate/premarket.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Gmail/__init__.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Htx/earn.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Htx/etype/__init__.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Htx/etype/ad.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Htx/etype/cred.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Htx/etype/pm.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Htx/etype/test.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/KuCoin/etype/ad.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/KuCoin/etype/pm.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/KuCoin/ex.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/KuCoin/web.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Mexc/etype/ad.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Mexc/etype/pm.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Mexc/ex.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Okx/etype/ad.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Okx/etype/pm.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Okx/ex.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/.gitignore +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Alfa/__init__.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Alfa/state.json +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/MTS/__init__.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Ozon/__init__.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Payeer/.gitignore +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Payeer/api.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Sber/__init__.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Sber/utils.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Tinkoff/__init__.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Volet/_todo_req/req.mjs +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Volet/_todo_req/req.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Volet/api.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Volet/pl.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Xync/ed.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Yandex/__init__.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/TgWallet/asset.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/TgWallet/auth.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/TgWallet/order.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/TgWallet/pyd.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/TgWallet/pyro.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/TgWallet/web.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/__init__.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/loader.py +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client.egg-info/dependency_links.txt +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client.egg-info/requires.txt +0 -0
- {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client.egg-info/top_level.txt +0 -0
|
@@ -3,7 +3,7 @@ import logging
|
|
|
3
3
|
import pytest
|
|
4
4
|
from tortoise.functions import Count
|
|
5
5
|
from xync_schema.enums import ExStatus, ExAction, UserStatus
|
|
6
|
-
from xync_schema.models import Ex, ExStat, Ad, Coin, Cur,
|
|
6
|
+
from xync_schema.models import Ex, ExStat, Ad, Coin, Cur, PmCur, Cred, CredEx, Actor, Person
|
|
7
7
|
from xync_schema.xtype import BaseAd
|
|
8
8
|
|
|
9
9
|
from xync_client.Abc.BaseTest import BaseTest
|
|
@@ -32,9 +32,9 @@ class TestAgent(BaseTest):
|
|
|
32
32
|
# 26
|
|
33
33
|
async def test_cred_new(self, clients: list[tuple[BaseAgentClient, BaseAgentClient]]):
|
|
34
34
|
for maker, taker in clients:
|
|
35
|
-
pmcur = await
|
|
35
|
+
pmcur = await PmCur.filter(pm__pmexs__ex=taker.actor.ex, cur__ticker="RUB", pm__norm="payeer").first()
|
|
36
36
|
cred = await Cred.create(person_id=taker.actor.person_id, name="Tst", detail="79990001234", pmcur=pmcur)
|
|
37
|
-
# await cred.banks.add(await
|
|
37
|
+
# await cred.banks.add(await PmExBank.get(exid="mts"), await PmExBank.get(exid="sberbankru"))
|
|
38
38
|
cred_new: CredEx = await taker.cred_new(cred)
|
|
39
39
|
ok = isinstance(cred_new, CredEx)
|
|
40
40
|
t, _ = await ExStat.update_or_create({"ok": ok}, ex=taker.actor.ex, action=ExAction.cred_new)
|
|
@@ -104,8 +104,8 @@ class TestEx(BaseTest):
|
|
|
104
104
|
# 24
|
|
105
105
|
async def test_ads(self, clients: list[BaseExClient]):
|
|
106
106
|
for client in clients:
|
|
107
|
-
cur = await models.
|
|
108
|
-
coin = await models.
|
|
107
|
+
cur = await models.CurEx.filter(cur__ticker="EUR", ex=client.ex).first().values_list("exid", flat=True)
|
|
108
|
+
coin = await models.CoinEx.filter(coin__ticker="USDT", ex=client.ex).first().values_list("exid", flat=True)
|
|
109
109
|
ads: list[BaseAd] = await client.ads(coin, cur, False)
|
|
110
110
|
ok = self.is_list_of_objects(ads, BaseAd)
|
|
111
111
|
t, _ = await models.ExStat.update_or_create({"ok": ok}, ex=client.ex, action=ExAction.ads)
|
|
@@ -123,10 +123,10 @@ class TestEx(BaseTest):
|
|
|
123
123
|
continue
|
|
124
124
|
for race in races:
|
|
125
125
|
# получаем данные направления текущей гонки
|
|
126
|
-
coinex = await models.
|
|
127
|
-
curex = await models.
|
|
126
|
+
coinex = await models.CoinEx.get(ex=client.ex, coin_id=race.road.ad.pair_side.pair.coin_id)
|
|
127
|
+
curex = await models.CurEx.get(ex=client.ex, cur_id=race.road.ad.pair_side.pair.cur_id)
|
|
128
128
|
pm_ids = [pm.id for pm in race.road.ad.pms]
|
|
129
|
-
pmex_exids = await models.
|
|
129
|
+
pmex_exids = await models.PmEx.filter(ex=client.ex, pm_id__in=pm_ids).values_list("exid", flat=True)
|
|
130
130
|
# получаем объявления по этому направлению
|
|
131
131
|
ads = await client.ads(coinex.exid, curex.exid, race.road.ad.pair_side.is_sell, pmex_exids)
|
|
132
132
|
# if race.vm_filter:
|
|
@@ -128,5 +128,5 @@ class BaseAgentClient(HttpClient):
|
|
|
128
128
|
# credex_in = models.CredEx.validate({"exid": cred_in.id, "cred_id": cred_db.id})
|
|
129
129
|
# credex_db, _ = await models.CredEx.update_or_create(**credex_in.df_unq())
|
|
130
130
|
# if banks: # only for SBP
|
|
131
|
-
# await cred_db.banks.add(*[await
|
|
131
|
+
# await cred_db.banks.add(*[await PmExBank.get(exid=b) for b in banks])
|
|
132
132
|
# return True
|
|
@@ -36,7 +36,7 @@ class BaseExClient(HttpClient):
|
|
|
36
36
|
super().__init__(getattr(ex, attr), headers, cookies, proxy and proxy.str())
|
|
37
37
|
|
|
38
38
|
@abstractmethod
|
|
39
|
-
def pm_type_map(self, typ: models.
|
|
39
|
+
def pm_type_map(self, typ: models.PmEx) -> str: ...
|
|
40
40
|
|
|
41
41
|
# 19: Список поддерживаемых валют тейкера
|
|
42
42
|
@abstractmethod
|
|
@@ -87,7 +87,7 @@ class BaseExClient(HttpClient):
|
|
|
87
87
|
async def countries(self) -> list[Struct]:
|
|
88
88
|
return []
|
|
89
89
|
|
|
90
|
-
# Импорт валют Cur-ов (с
|
|
90
|
+
# Импорт валют Cur-ов (с CurEx-ами)
|
|
91
91
|
async def set_curs(self, cookies: dict = None) -> bool:
|
|
92
92
|
# Curs
|
|
93
93
|
cur_pyds: dict[str, CurEx] = await self.curs()
|
|
@@ -96,14 +96,12 @@ class BaseExClient(HttpClient):
|
|
|
96
96
|
for exid, cur_pyd in cur_pyds.items()
|
|
97
97
|
}
|
|
98
98
|
curexs = [
|
|
99
|
-
models.
|
|
99
|
+
models.CurEx(**c.model_dump(exclude_none=True), cur=curs[c.exid], ex=self.ex) for c in cur_pyds.values()
|
|
100
100
|
]
|
|
101
|
-
#
|
|
102
|
-
await models.
|
|
103
|
-
curexs, update_fields=["minimum", "rounding_scale"], on_conflict=["cur_id", "ex_id"]
|
|
104
|
-
)
|
|
101
|
+
# CurEx
|
|
102
|
+
await models.CurEx.bulk_create(curexs, update_fields=["minimum", "scale"], on_conflict=["cur_id", "ex_id"])
|
|
105
103
|
|
|
106
|
-
# Импорт Pm-ов (с
|
|
104
|
+
# Импорт Pm-ов (с PmCur-, PmEx- и Pmcurex-ами) и валют (с CurEx-ами) с биржи в бд
|
|
107
105
|
async def set_pms(self, cookies: dict = None) -> bool:
|
|
108
106
|
if cookies:
|
|
109
107
|
self.session.cookie_jar.update_cookies(cookies)
|
|
@@ -134,19 +132,19 @@ class BaseExClient(HttpClient):
|
|
|
134
132
|
logging.warning(f"Pm: '{pmex.name}' duplicated with ids {prev[0]}: {k} on {self.ex.name}")
|
|
135
133
|
# новый Pm не добавляем, а берем старый с этим названием
|
|
136
134
|
pm_ = pms.get(prev[0], await models.Pm.get_or_none(norm=prev[1], country_id=country_id))
|
|
137
|
-
# и добавляем
|
|
138
|
-
await models.
|
|
135
|
+
# и добавляем PmEx для него
|
|
136
|
+
await models.PmEx.update_or_create({"name": pmex.name}, ex=self.ex, exid=k, pm=pm_)
|
|
139
137
|
elif (
|
|
140
138
|
prev[1] == pmu.norm and pmu.country == prev[3]
|
|
141
139
|
): # 2 разных оригинальных имени на этой бирже совпали при нормализации
|
|
142
140
|
logging.error(
|
|
143
141
|
f"Pm: {pmex.name}&{prev[2]} overnormd as {pmu.norm} with ids {prev[0]}: {k} on {self.ex.name}"
|
|
144
142
|
)
|
|
145
|
-
# новый Pm не добавляем, только
|
|
143
|
+
# новый Pm не добавляем, только PmEx для него
|
|
146
144
|
# новый Pm не добавляем, а берем старый с этим названием
|
|
147
145
|
pm_ = pms.get(prev[0], await models.Pm.get_or_none(norm=prev[1], country_id=country_id))
|
|
148
|
-
# и добавляем.обновляем
|
|
149
|
-
await models.
|
|
146
|
+
# и добавляем.обновляем PmEx для него
|
|
147
|
+
await models.PmEx.update_or_create({"pm": pm_}, ex=self.ex, exid=k, name=pmex.name)
|
|
150
148
|
else:
|
|
151
149
|
pmin = models.Pm.validate({**pmu.model_dump(), "country_id": country_id, "typ": pmex.typ})
|
|
152
150
|
try:
|
|
@@ -154,14 +152,14 @@ class BaseExClient(HttpClient):
|
|
|
154
152
|
except (MultipleObjectsReturned, IntegrityError) as e:
|
|
155
153
|
raise e
|
|
156
154
|
prev = k, pmu.norm, pmex.name, pmu.country
|
|
157
|
-
await models.
|
|
155
|
+
await models.PmCur.update_or_create( # todo: NA HU YA???
|
|
158
156
|
cur=await models.Cur.get(ticker="THB"), pm=await models.Pm.get(norm="cash in person")
|
|
159
157
|
)
|
|
160
158
|
|
|
161
159
|
# Pmexs
|
|
162
160
|
async with ClientSession(headers=getattr(self, "logo_headers", None)) as ss:
|
|
163
161
|
pmexs = [
|
|
164
|
-
models.
|
|
162
|
+
models.PmEx(
|
|
165
163
|
# todo: refact logo
|
|
166
164
|
exid=k,
|
|
167
165
|
ex=self.ex,
|
|
@@ -172,13 +170,13 @@ class BaseExClient(HttpClient):
|
|
|
172
170
|
for k, pm in pms.items()
|
|
173
171
|
]
|
|
174
172
|
|
|
175
|
-
await models.
|
|
176
|
-
#
|
|
173
|
+
await models.PmEx.bulk_create(pmexs, on_conflict=["ex_id", "exid"], update_fields=["pm_id", "logo_id", "name"])
|
|
174
|
+
# PmEx banks
|
|
177
175
|
for k, pmex in pmexs_epyds.items():
|
|
178
176
|
if banks := pmex.banks:
|
|
179
|
-
pmex = await models.
|
|
177
|
+
pmex = await models.PmEx.get(ex=self.ex, exid=k) # pm=pms[k],
|
|
180
178
|
for b in banks:
|
|
181
|
-
await models.
|
|
179
|
+
await models.PmExBank.update_or_create({"name": b.name}, exid=b.exid, pmex=pmex)
|
|
182
180
|
|
|
183
181
|
cur2pms = await self.cur_pms_map()
|
|
184
182
|
# # Link PayMethods with currencies
|
|
@@ -186,13 +184,13 @@ class BaseExClient(HttpClient):
|
|
|
186
184
|
for cur_id, exids in cur2pms.items():
|
|
187
185
|
for exid in exids:
|
|
188
186
|
if not (pm_id := pms.get(exid) and pms[exid].id):
|
|
189
|
-
if pmex := await models.
|
|
187
|
+
if pmex := await models.PmEx.get_or_none(ex=self.ex, exid=exid):
|
|
190
188
|
pm_id = pmex.pm_id
|
|
191
189
|
else:
|
|
192
190
|
logging.critical(f"For cur {cur_id} not found pm#{exid}")
|
|
193
191
|
continue
|
|
194
192
|
if cur_db := curs.get(cur_id):
|
|
195
|
-
pmcurs.add((await models.
|
|
193
|
+
pmcurs.add((await models.PmCur.update_or_create(cur=cur_db, pm_id=pm_id))[0])
|
|
196
194
|
# pmcurexs = [Pmcurex(pmcur=pmcur, ex=self.ex) for pmcur in pmcurs]
|
|
197
195
|
# await Pmcurex.bulk_create(pmcurexs)
|
|
198
196
|
return True
|
|
@@ -206,7 +204,7 @@ class BaseExClient(HttpClient):
|
|
|
206
204
|
return await self.file_upsert(url, ss)
|
|
207
205
|
return file
|
|
208
206
|
|
|
209
|
-
# Импорт монет (с
|
|
207
|
+
# Импорт монет (с CoinEx-ами) с биржи в бд
|
|
210
208
|
async def set_coins(self):
|
|
211
209
|
coins: dict[str, CoinEx] = await self.coins()
|
|
212
210
|
coins_db: dict[int, models.Coin] = {
|
|
@@ -215,10 +213,10 @@ class BaseExClient(HttpClient):
|
|
|
215
213
|
)[0]
|
|
216
214
|
for c in coins.values()
|
|
217
215
|
}
|
|
218
|
-
coinexs: list[models.
|
|
219
|
-
models.
|
|
216
|
+
coinexs: list[models.CoinEx] = [
|
|
217
|
+
models.CoinEx(coin=coins_db[c.exid], ex=self.ex, exid=c.exid, minimum=c.minimum) for c in coins.values()
|
|
220
218
|
]
|
|
221
|
-
await models.
|
|
219
|
+
await models.CoinEx.bulk_create(coinexs, update_fields=["minimum"], on_conflict=["coin_id", "ex_id"])
|
|
222
220
|
return True
|
|
223
221
|
|
|
224
222
|
# Импорт пар биржи в бд
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
from abc import abstractmethod, ABCMeta
|
|
2
|
+
from asyncio import get_running_loop
|
|
3
|
+
from datetime import datetime, timedelta
|
|
2
4
|
from decimal import Decimal
|
|
3
5
|
from enum import StrEnum
|
|
4
6
|
|
|
@@ -25,6 +27,8 @@ class PmAgentClient(metaclass=ABCMeta):
|
|
|
25
27
|
bot: FileClient
|
|
26
28
|
page: Page
|
|
27
29
|
pages: type(StrEnum) = Pages
|
|
30
|
+
last_page: int = 0
|
|
31
|
+
last_active: datetime = datetime.now()
|
|
28
32
|
_is_started: bool = False
|
|
29
33
|
|
|
30
34
|
async def start(self, pw: Playwright, headed: bool = False) -> "PmAgentClient":
|
|
@@ -49,15 +53,18 @@ class PmAgentClient(metaclass=ABCMeta):
|
|
|
49
53
|
if not self.page.url.startswith(self.pages.SEND): # Если в итоге не удалось попасть на отправку
|
|
50
54
|
await self.bot.send(self.norm + " not logged in!", self.uid, photo=await self.page.screenshot())
|
|
51
55
|
raise LoginFailedException(f"User {self.agent.user_id} has not logged in")
|
|
52
|
-
|
|
53
|
-
|
|
56
|
+
loop = get_running_loop()
|
|
57
|
+
self.last_active = datetime.now()
|
|
58
|
+
loop.create_task(self._idle()) # Бесконечно пасёмся в фоне на странице отправки, что бы куки не протухли
|
|
54
59
|
self._is_started = True
|
|
55
60
|
return self
|
|
56
61
|
|
|
57
62
|
async def _idle(self): # todo: не мешать другим процессам, обновлять на другой вкладке?
|
|
58
63
|
while (await User.get(username_id=self.uid)).status >= UserStatus.ACTIVE:
|
|
59
|
-
await self.page.wait_for_timeout(
|
|
60
|
-
|
|
64
|
+
await self.page.wait_for_timeout(15 * 1000)
|
|
65
|
+
if self.last_active < datetime.now() - timedelta(seconds=20):
|
|
66
|
+
await self.page.reload()
|
|
67
|
+
self.last_active = datetime.now()
|
|
61
68
|
await self.bot.send(self.norm + " stoped", self.uid)
|
|
62
69
|
await self.stop()
|
|
63
70
|
|
|
@@ -75,7 +82,7 @@ class PmAgentClient(metaclass=ABCMeta):
|
|
|
75
82
|
async def _login(self): ...
|
|
76
83
|
|
|
77
84
|
@abstractmethod
|
|
78
|
-
async def send(self, dest, amount: int, cur: str) -> tuple[int, bytes]: ...
|
|
85
|
+
async def send(self, dest, amount: int, cur: str) -> tuple[int, bytes, float]: ...
|
|
79
86
|
|
|
80
87
|
@abstractmethod # проверка поступления определенной суммы за последние пол часа (минимум), return точную сумму
|
|
81
88
|
async def check_in(self, amount: int | Decimal | float, cur: str, tid: str | int = None) -> float | None: ...
|
|
@@ -4,7 +4,7 @@ from pydantic import BaseModel, model_validator
|
|
|
4
4
|
from x_model.types import BaseUpd
|
|
5
5
|
from xync_schema.enums import PmType
|
|
6
6
|
from xync_schema.models import Country, Pm, Ex
|
|
7
|
-
from xync_schema.xtype import
|
|
7
|
+
from xync_schema.xtype import PmExBank
|
|
8
8
|
|
|
9
9
|
from xync_client.pm_unifier import PmUni
|
|
10
10
|
|
|
@@ -17,7 +17,7 @@ MapOfIdsList = dict[int | str, list[int | str]]
|
|
|
17
17
|
class PmTrait:
|
|
18
18
|
typ: PmType | None = None
|
|
19
19
|
logo: str | None = None
|
|
20
|
-
banks: list[
|
|
20
|
+
banks: list[PmExBank] | None = None
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
class PmEx(BaseModel, PmTrait):
|
|
@@ -2,7 +2,8 @@ from xync_client.Abc.Agent import BaseAgentClient
|
|
|
2
2
|
from xync_schema.pydantic import FiatNew
|
|
3
3
|
from xync_schema.models import Cur, Fiat
|
|
4
4
|
from xync_client.Abc.Base import DictOfDicts
|
|
5
|
-
from xync_schema.models import
|
|
5
|
+
from xync_schema.models import Coin, OrderStatus
|
|
6
|
+
|
|
6
7
|
|
|
7
8
|
class AgentClient(BaseAgentClient):
|
|
8
9
|
headers = {
|
|
@@ -37,18 +38,20 @@ class AgentClient(BaseAgentClient):
|
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
# 0: Получшение заявок за заданное время, в статусе, по валюте, монете
|
|
40
|
-
async def get_orders(
|
|
41
|
+
async def get_orders(
|
|
42
|
+
self, status: OrderStatus = OrderStatus.created, coin: Coin = None, cur: Cur = None, is_sell: bool = None
|
|
43
|
+
):
|
|
41
44
|
params = {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
45
|
+
"pageId": "0",
|
|
46
|
+
"pageSize": "10",
|
|
47
|
+
"messageStatus": "0",
|
|
48
|
+
"orderType": "1",
|
|
49
|
+
"orderStatus": "",
|
|
50
|
+
"fiat": "",
|
|
51
|
+
"searchKeyword": "",
|
|
52
|
+
"tradeType": "",
|
|
53
|
+
"beginTime": "1706475600000",
|
|
54
|
+
"endTime": "1738184399999",
|
|
52
55
|
}
|
|
53
56
|
order = await self._get("/api/c2c/v2/order/list", params=params)
|
|
54
57
|
return order["data"]["result"]
|
|
@@ -56,14 +59,14 @@ class AgentClient(BaseAgentClient):
|
|
|
56
59
|
# 1: [T] Запрос на старт сделки
|
|
57
60
|
async def order_request(self, ad_id: int, amount: float):
|
|
58
61
|
json_data = {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
"advertNo": f"{ad_id}",
|
|
63
|
+
"asset": "USDT",
|
|
64
|
+
"fiat": "RUB",
|
|
65
|
+
"type": 1,
|
|
66
|
+
"userPrice": 103,
|
|
67
|
+
"areaType": 2,
|
|
68
|
+
"amount": f"{amount}",
|
|
69
|
+
"paymentMethodId": 110,
|
|
67
70
|
}
|
|
68
71
|
order = await self._post("/api/c2c/v1/order/create", json=json_data)
|
|
69
72
|
if order["data"]:
|
|
@@ -2,7 +2,7 @@ import json
|
|
|
2
2
|
import logging
|
|
3
3
|
import re
|
|
4
4
|
from datetime import datetime, timezone
|
|
5
|
-
|
|
5
|
+
from uuid import uuid4
|
|
6
6
|
|
|
7
7
|
import websockets
|
|
8
8
|
from asyncio import run
|
|
@@ -10,6 +10,9 @@ from decimal import Decimal
|
|
|
10
10
|
|
|
11
11
|
from playwright.async_api import async_playwright
|
|
12
12
|
from pyro_client.client.file import FileClient
|
|
13
|
+
from tortoise.transactions import in_transaction
|
|
14
|
+
from xync_schema.models import CredEx
|
|
15
|
+
|
|
13
16
|
from xync_client.Abc.PmAgent import PmAgentClient
|
|
14
17
|
from xync_schema import models
|
|
15
18
|
from xync_schema.enums import UserStatus, OrderStatus
|
|
@@ -89,17 +92,22 @@ class InAgentClient(BaseInAgentClient):
|
|
|
89
92
|
dest = order.paymentTermList[0].accountNo
|
|
90
93
|
if not re.match(r"^P\d{8,10}$", dest):
|
|
91
94
|
continue
|
|
92
|
-
await order_db.fetch_related("cred__pmcur__cur")
|
|
93
|
-
|
|
94
|
-
await self.send_payment(order_db, dest)
|
|
95
|
-
...
|
|
95
|
+
await order_db.fetch_related("ad__pair_side__pair", "cred__pmcur__cur")
|
|
96
|
+
await self.send_payment(order_db, dest)
|
|
96
97
|
case StatusApi.wait_for_buyer:
|
|
97
98
|
if upd.side == 0: # ждем когда покупатель оплатит
|
|
98
99
|
if not (pmacdx := await self.get_pma_by_cdex(order)):
|
|
99
100
|
continue
|
|
100
101
|
pma, cdx = pmacdx
|
|
101
|
-
am, tid = pma.check_in(
|
|
102
|
+
am, tid = pma.check_in(
|
|
103
|
+
Decimal(order.amount),
|
|
104
|
+
cdx.cred.pmcur.cur.ticker,
|
|
105
|
+
datetime.fromtimestamp(float(order.createDate) / 1000),
|
|
106
|
+
)
|
|
102
107
|
if not tid:
|
|
108
|
+
logging.info(
|
|
109
|
+
f"Order {order.id} created at {order.createDate}, not paid yet"
|
|
110
|
+
)
|
|
103
111
|
continue
|
|
104
112
|
t, is_new = await models.Transfer.update_or_create(
|
|
105
113
|
dict(
|
|
@@ -109,15 +117,26 @@ class InAgentClient(BaseInAgentClient):
|
|
|
109
117
|
order=order_db,
|
|
110
118
|
pmid=tid,
|
|
111
119
|
)
|
|
112
|
-
if is_new:
|
|
120
|
+
if not is_new:
|
|
121
|
+
continue
|
|
122
|
+
await order_db.fetch_related("ad__pair_side__pair")
|
|
123
|
+
async with in_transaction():
|
|
124
|
+
# добавляем остаток монеты
|
|
125
|
+
ass = await models.Asset.get(
|
|
126
|
+
addr__coin_id=order_db.ad.pair_side.pair.coin_id,
|
|
127
|
+
addr__actor=self.agent_client.actor,
|
|
128
|
+
)
|
|
129
|
+
ass.free -= float(order_db.amount / order_db.ad.price)
|
|
130
|
+
await ass.save(update_fields=["free"])
|
|
131
|
+
# обновляем остаток валюты
|
|
132
|
+
fiat = await models.Fiat.get(cred_id=order_db.cred_id)
|
|
133
|
+
fiat.amount += order_db.amount
|
|
134
|
+
await fiat.save(update_fields=["amount"])
|
|
135
|
+
# отправляем деньги
|
|
113
136
|
self.agent_client.api.release_assets(orderId=upd.id)
|
|
114
137
|
logging.info(
|
|
115
138
|
f"Order {order.id} created, paid before #{tid}:{am} at {order.createDate}, and RELEASED at {datetime.now()}"
|
|
116
139
|
)
|
|
117
|
-
else:
|
|
118
|
-
logging.info(
|
|
119
|
-
f"Order {order.id} created at {order.createDate} but no paid yet"
|
|
120
|
-
)
|
|
121
140
|
elif upd.side == 1: # я покупатель - ждем мою оплату
|
|
122
141
|
continue # logging.warning(f"Order {order.id} PAID at {datetime.now()}: {int_am}")
|
|
123
142
|
else:
|
|
@@ -173,7 +192,7 @@ class InAgentClient(BaseInAgentClient):
|
|
|
173
192
|
upd = Receive.model_validate(data["data"])
|
|
174
193
|
if order_db := await models.Order.get_or_none(
|
|
175
194
|
exid=upd.orderId, ad__maker__ex=self.agent_client.actor.ex
|
|
176
|
-
).prefetch_related("
|
|
195
|
+
).prefetch_related("ad__pair_side__pair", "cred__pmcur__cur"):
|
|
177
196
|
im_taker = order_db.taker_id == self.agent_client.actor.id
|
|
178
197
|
im_buyer = order_db.ad.pair_side.is_sell == im_taker
|
|
179
198
|
if order_db.ad.auto_msg != upd.message and upd.roleType not in ("sys", "alarm"):
|
|
@@ -188,9 +207,7 @@ class InAgentClient(BaseInAgentClient):
|
|
|
188
207
|
if not upd.message:
|
|
189
208
|
...
|
|
190
209
|
if im_buyer and re.match(r"^P\d{8,10}$", upd.message):
|
|
191
|
-
|
|
192
|
-
await self.send_payment(order_db, upd.message)
|
|
193
|
-
...
|
|
210
|
+
await self.send_payment(order_db, upd.message)
|
|
194
211
|
case "READ":
|
|
195
212
|
upd = Read.model_validate(data["data"])
|
|
196
213
|
# if upd.status not in (StatusWs.created, StatusWs.canceled, 10, StatusWs.completed):
|
|
@@ -227,33 +244,53 @@ class InAgentClient(BaseInAgentClient):
|
|
|
227
244
|
if not upd:
|
|
228
245
|
logging.warning(data, "NOT PROCESSED UPDATE")
|
|
229
246
|
|
|
230
|
-
async def send_payment(self, order_db: models.Order, dest)
|
|
247
|
+
async def send_payment(self, order_db: models.Order, dest):
|
|
248
|
+
if order_db.status not in (OrderStatus.created, OrderStatus.requested):
|
|
249
|
+
return
|
|
231
250
|
int_am = int(float(order_db.amount))
|
|
232
251
|
pma, cur = await self.get_pma_by_pmex(order_db)
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
252
|
+
async with in_transaction():
|
|
253
|
+
# отмечаем ордер на бирже "оплачен"
|
|
254
|
+
pmex = await models.PmEx.get(pm_id=order_db.cred.pmcur.pm_id, ex=self.agent_client.actor.ex)
|
|
255
|
+
credex = await models.CredEx.get(cred=order_db.cred, ex=self.agent_client.actor.ex)
|
|
256
|
+
self.agent_client.api.mark_as_paid(
|
|
257
|
+
orderId=str(order_db.exid),
|
|
258
|
+
paymentType=pmex.exid, # pmex.exid
|
|
259
|
+
paymentId=str(credex.exid), # credex.exid
|
|
260
|
+
)
|
|
261
|
+
# проверяем не отправляли ли мы уже перевод по этому ордеру
|
|
262
|
+
if t := await models.Transfer.get_or_none(order=order_db, amount=int_am):
|
|
263
|
+
await pma.bot.send(f"Order# {order_db.exid}: Double send {int_am}{cur} to {dest} #{t.pmid}!")
|
|
264
|
+
raise Exception(f"Order# {order_db.exid}: Double send {int_am}{cur} to {dest} #{t.pmid}!")
|
|
265
|
+
|
|
266
|
+
# ставим в бд статус "оплачен"
|
|
267
|
+
order_db.status = OrderStatus.paid
|
|
268
|
+
order_db.payed_at = datetime.now(timezone.utc)
|
|
269
|
+
await order_db.save()
|
|
270
|
+
# добавляем остаток монеты
|
|
271
|
+
ass = await models.Asset.get(
|
|
272
|
+
addr__coin_id=order_db.ad.pair_side.pair.coin_id, addr__actor=self.agent_client.actor
|
|
273
|
+
)
|
|
274
|
+
ass.free += float(order_db.amount / order_db.ad.price)
|
|
275
|
+
await ass.save(update_fields=["free"])
|
|
276
|
+
# отправляем деньги
|
|
277
|
+
tid, img, rest_amount = await pma.send(dest=dest, amount=int_am, cur=cur)
|
|
278
|
+
# создаем перевод в бд
|
|
279
|
+
t, _ = await models.Transfer.update_or_create(
|
|
280
|
+
{"amount": int_am * 100},
|
|
281
|
+
order=order_db,
|
|
282
|
+
pmid=tid,
|
|
283
|
+
)
|
|
284
|
+
# обновляем остаток валюты
|
|
285
|
+
await models.Fiat.update_or_create({"amount": rest_amount}, cred_id=order_db.cred_id)
|
|
286
|
+
# отправляем продавцу чек
|
|
287
|
+
if res := self.agent_client.api.upload_chat_file(upload_file=f"tmp/{dest}.png").get("result"):
|
|
288
|
+
self.agent_client.api.send_chat_message(
|
|
289
|
+
orderId=str(order_db.exid), contentType="pic", message=res["url"], msgUuid=uuid4().hex
|
|
290
|
+
)
|
|
291
|
+
logging.info(f"Order {order_db.exid} PAID at {datetime.now()}: {int_am}!")
|
|
255
292
|
|
|
256
|
-
async def get_pma_by_cdex(self, order: OrderFull) -> tuple[PmAgentClient,
|
|
293
|
+
async def get_pma_by_cdex(self, order: OrderFull) -> tuple[PmAgentClient | None, CredEx] | None:
|
|
257
294
|
cdxs = await models.CredEx.filter(
|
|
258
295
|
ex=self.agent_client.ex_client.ex,
|
|
259
296
|
exid__in=[ptl.id for ptl in order.paymentTermList],
|
|
@@ -261,7 +298,7 @@ class InAgentClient(BaseInAgentClient):
|
|
|
261
298
|
).prefetch_related("cred__pmcur__cur")
|
|
262
299
|
pmas = [pma for cdx in cdxs if (pma := self.pmacs.get(cdx.cred.pmcur.pm_id))]
|
|
263
300
|
if not len(pmas):
|
|
264
|
-
|
|
301
|
+
raise Exception(order.paymentTermList, f"No pm_agents for {order.paymentTermList[0].paymentType}")
|
|
265
302
|
elif len(pmas) > 1:
|
|
266
303
|
logging.error(order.paymentTermList, f">1 pm_agents for {cdxs[0].cred.pmcur.pm_id}")
|
|
267
304
|
else:
|