xync-client 0.0.25.dev0__tar.gz → 0.0.25.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.25.dev0/xync_client.egg-info → xync_client-0.0.25.dev4}/PKG-INFO +1 -1
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/README.md +7 -1
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/tests/TestEx.py +26 -11
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Abc/Agent.py +1 -1
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Abc/BaseTest.py +14 -7
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Abc/Ex.py +39 -18
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/BitGet/ex.py +2 -2
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/TgWallet/agent.py +10 -25
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/TgWallet/ex.py +53 -29
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/TgWallet/pyd.py +17 -7
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4/xync_client.egg-info}/PKG-INFO +1 -1
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client.egg-info/SOURCES.txt +0 -1
- xync_client-0.0.25.dev0/xync_client/pyd.py +0 -71
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/.env.sample +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/.gitignore +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/.pre-commit-config.yaml +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/makefile +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/pyproject.toml +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/setup.cfg +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/tests/TestAgent.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/tests/TestAsset.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/tests/TestOrder.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/tests/_todo_refact/Binance/test_binance.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/tests/_todo_refact/Bybit/test_bybit.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/tests/_todo_refact/Bybit/test_bybit_p2p.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/tests/_todo_refact/Gate/test_gate.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/tests/_todo_refact/Htx/test_htx_p2p.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/tests/_todo_refact/Wallet/test_agent.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/tests/_todo_refact/Wallet/test_ex.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/tests/_todo_refact/__init__.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/tests/_todo_refact/_test_ex.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Abc/Asset.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Abc/AuthTrait.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Abc/Base.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Abc/InAgent.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Abc/Order.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Binance/__init__.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Binance/binance_async.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Binance/earn_api.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Binance/ex.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Binance/exceptions.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Binance/sapi.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Binance/web_c2c.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/BingX/__init__.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/BingX/agent.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/BingX/base.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/BingX/ex.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/BingX/req.mjs +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/BingX/sign.js +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/BingX/test/main.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/BitGet/__init__.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/BitGet/agent.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/BitGet/req.mjs +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Bybit/agent.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Bybit/ex.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Bybit/web_earn.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Bybit/web_p2p.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Gate/ex.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Gate/premarket.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Htx/agent.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Htx/earn.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Htx/ex.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/KuCoin/pub.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/KuCoin/web.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/Okx/ex.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/TgWallet/asset.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/TgWallet/auth.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/TgWallet/inAgent.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/TgWallet/order.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/TgWallet/pyro.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/TgWallet/web.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/__init__.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client/loader.py +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client.egg-info/dependency_links.txt +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client.egg-info/requires.txt +0 -0
- {xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client.egg-info/top_level.txt +0 -0
|
@@ -136,6 +136,8 @@ classDef red stroke:#f00
|
|
|
136
136
|
- 22: Список торгуемых монет (с ограничениям по валютам, если есть) `coins() => [Coin]`
|
|
137
137
|
- 23: Список пар валюта/монет `pairs() => [Pair]`
|
|
138
138
|
- 24: Список объяв по (buy/sell, cur, coin, pm) `ads(coin: Coin, cur: Cur, is_sell: bool, pms:list[Pm]=None)`
|
|
139
|
+
- 42: Минимальные объемы валют в объявлении `cur_mins() => FlatDict`
|
|
140
|
+
- 43: Минимальные объемы монет в объявлении `coin_mins() => FlatDict`
|
|
139
141
|
|
|
140
142
|
### Fiat
|
|
141
143
|
- 25: Список реквизитов моих платежных методов `my_fiats(cur:Cur=None) => [Fiat]`
|
|
@@ -162,4 +164,8 @@ classDef red stroke:#f00
|
|
|
162
164
|
- 38N: Получение уведомления о полученном отзыве `got_rated => (user_id:int, order_id:int)`
|
|
163
165
|
|
|
164
166
|
### Assets
|
|
165
|
-
-
|
|
167
|
+
- 41: Получить балансы моих монет: `my_assets() => list[Asset]`
|
|
168
|
+
- 40: Получить реквизиты для депозита монеты `deposit(amount: int) => bool`
|
|
169
|
+
- 40N: Получена монета `deposited => amount`
|
|
170
|
+
- 41: Вывести монету `withdraw(amount: int) => bool`
|
|
171
|
+
- 41N: Монета выведена `withdrew => amount`
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
|
+
from xync_schema.pydantic import PmPyd, BaseAd
|
|
5
|
+
|
|
4
6
|
from xync_client.Abc.BaseTest import BaseTest
|
|
5
7
|
from xync_schema.enums import ExStatus, ExType, ExAction
|
|
6
8
|
from xync_schema.models import Ex, TestEx as ExTest
|
|
7
9
|
|
|
8
|
-
from xync_client.Abc.Base import BaseClient,
|
|
10
|
+
from xync_client.Abc.Base import BaseClient, FlatDict, MapOfIdsList
|
|
9
11
|
from xync_client.Abc.Ex import BaseExClient
|
|
10
12
|
|
|
11
13
|
|
|
12
14
|
@pytest.mark.asyncio(loop_scope="session")
|
|
13
15
|
class TestEx(BaseTest):
|
|
16
|
+
ad: dict[str, BaseAd] = {}
|
|
17
|
+
|
|
14
18
|
@pytest.fixture
|
|
15
19
|
async def clients(self) -> list[BaseClient]:
|
|
16
20
|
exs = await Ex.filter(status__gt=ExStatus.plan)
|
|
@@ -26,15 +30,16 @@ class TestEx(BaseTest):
|
|
|
26
30
|
ok = self.is_flat_dict(curs)
|
|
27
31
|
t, _ = await ExTest.update_or_create({"ok": ok}, ex=client.ex, action=ExAction.curs)
|
|
28
32
|
assert t.ok, "No curs"
|
|
29
|
-
logging.info(f"{client.ex.name}:{ExAction.curs.name} - ok")
|
|
33
|
+
logging.info(f"{client.ex.name}: {ExAction.curs.name} - ok")
|
|
30
34
|
|
|
31
35
|
# 20
|
|
32
36
|
async def test_pms(self, clients: list[BaseExClient]):
|
|
33
37
|
for client in clients:
|
|
34
|
-
pms:
|
|
35
|
-
|
|
38
|
+
pms: dict[int | str, PmPyd] = await client.pms()
|
|
39
|
+
ok = self.is_dict_of_objects(pms, PmPyd)
|
|
40
|
+
t, _ = await ExTest.update_or_create({"ok": ok}, ex=client.ex, action=ExAction.pms)
|
|
36
41
|
assert t.ok, "No pms"
|
|
37
|
-
logging.info(f"{client.ex.name}:{ExAction.pms.name} - ok")
|
|
42
|
+
logging.info(f"{client.ex.name}: {ExAction.pms.name} - ok")
|
|
38
43
|
|
|
39
44
|
# 21
|
|
40
45
|
async def test_cur_pms_map(self, clients: list[BaseExClient]):
|
|
@@ -43,7 +48,7 @@ class TestEx(BaseTest):
|
|
|
43
48
|
ok = self.is_map_of_ids(cur_pms)
|
|
44
49
|
t, _ = await ExTest.update_or_create({"ok": ok}, ex=client.ex, action=ExAction.cur_pms_map)
|
|
45
50
|
assert t.ok, "No pms for cur"
|
|
46
|
-
logging.info(f"{client.ex.name}:{ExAction.cur_pms_map.name} - ok")
|
|
51
|
+
logging.info(f"{client.ex.name}: {ExAction.cur_pms_map.name} - ok")
|
|
47
52
|
|
|
48
53
|
# 22
|
|
49
54
|
async def test_coins(self, clients: list[BaseExClient]):
|
|
@@ -52,7 +57,7 @@ class TestEx(BaseTest):
|
|
|
52
57
|
ok = self.is_flat_dict(coins)
|
|
53
58
|
t, _ = await ExTest.update_or_create({"ok": ok}, ex=client.ex, action=ExAction.coins)
|
|
54
59
|
assert t.ok, "No coins"
|
|
55
|
-
logging.info(f"{client.ex.name}:{ExAction.coins.name} - ok")
|
|
60
|
+
logging.info(f"{client.ex.name}: {ExAction.coins.name} - ok")
|
|
56
61
|
|
|
57
62
|
# 23
|
|
58
63
|
async def test_pairs(self, clients: list[BaseExClient]):
|
|
@@ -61,13 +66,23 @@ class TestEx(BaseTest):
|
|
|
61
66
|
ok = self.is_map_of_ids(pairs)
|
|
62
67
|
t, _ = await ExTest.update_or_create({"ok": ok}, ex=client.ex, action=ExAction.pairs)
|
|
63
68
|
assert t.ok, "No coins"
|
|
64
|
-
logging.info(f"{client.ex.name}:{ExAction.pairs.name} - ok")
|
|
69
|
+
logging.info(f"{client.ex.name}: {ExAction.pairs.name} - ok")
|
|
65
70
|
|
|
66
71
|
# 24
|
|
67
72
|
async def test_ads(self, clients: list[BaseExClient]):
|
|
68
73
|
for client in clients:
|
|
69
|
-
ads:
|
|
70
|
-
ok = self.
|
|
74
|
+
ads: list[BaseAd] = await client.ads("USDT", "RUB", False)
|
|
75
|
+
ok = self.is_list_of_objects(ads, BaseAd)
|
|
71
76
|
t, _ = await ExTest.update_or_create({"ok": ok}, ex=client.ex, action=ExAction.ads)
|
|
72
77
|
assert t.ok, "No ads"
|
|
73
|
-
|
|
78
|
+
self.ad[client.ex.name] = ads[0] # for further use in test_ad
|
|
79
|
+
logging.info(f"{client.ex.name}: {ExAction.ads.name} - ok")
|
|
80
|
+
|
|
81
|
+
# 42
|
|
82
|
+
async def test_ad(self, clients: list[BaseExClient]):
|
|
83
|
+
for client in clients:
|
|
84
|
+
ad: BaseAd = await client.ad(self.ad[client.ex.name].id)
|
|
85
|
+
ok = isinstance(ad, BaseAd)
|
|
86
|
+
t, _ = await ExTest.update_or_create({"ok": ok}, ex=client.ex, action=ExAction.ad)
|
|
87
|
+
assert t.ok, "No ad"
|
|
88
|
+
logging.info(f"{client.ex.name}: {ExAction.ad.name} - ok")
|
|
@@ -83,7 +83,7 @@ class BaseAgentClient(BaseClient, BaseAuthTrait): # todo: inherit form Base or
|
|
|
83
83
|
|
|
84
84
|
# 25: Список реквизитов моих платежных методов
|
|
85
85
|
@abstractmethod
|
|
86
|
-
async def fiats(self
|
|
86
|
+
async def fiats(self) -> ListOfDicts: ... # {fiat.exid: {fiat}}
|
|
87
87
|
|
|
88
88
|
@staticmethod
|
|
89
89
|
async def fiat_pyd2db(fiat_pyd: FiatNew | FiatUpd, uid: int, fid: int = None) -> tuple[Fiat, bool]:
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
from abc import abstractmethod
|
|
2
|
-
|
|
3
|
-
# from asyncio import AbstractEventLoop
|
|
4
|
-
from typing import TypeGuard
|
|
5
|
-
|
|
6
1
|
import pytest
|
|
7
2
|
|
|
8
3
|
# import uvloop
|
|
4
|
+
from abc import abstractmethod
|
|
5
|
+
from typing import TypeGuard
|
|
9
6
|
from tortoise.backends.asyncpg import AsyncpgDBClient
|
|
10
7
|
from x_model import init_db
|
|
11
8
|
from xync_client.Abc.Base import BaseClient, DictOfDicts, ListOfDicts, FlatDict, MapOfIdsList
|
|
@@ -16,11 +13,9 @@ from xync_client.loader import PG_DSN
|
|
|
16
13
|
|
|
17
14
|
class BaseTest:
|
|
18
15
|
# loop: AbstractEventLoop
|
|
19
|
-
|
|
20
16
|
# @pytest.fixture(scope="session", autouse=True)
|
|
21
17
|
# def event_loop_policy(self):
|
|
22
18
|
# return uvloop.EventLoopPolicy()
|
|
23
|
-
|
|
24
19
|
@pytest.fixture(scope="session", autouse=True)
|
|
25
20
|
async def cn(self) -> AsyncpgDBClient:
|
|
26
21
|
cn: AsyncpgDBClient = await init_db(PG_DSN, models, True)
|
|
@@ -37,12 +32,24 @@ class BaseTest:
|
|
|
37
32
|
return False
|
|
38
33
|
return all(isinstance(k, int | str) and isinstance(v, dict) for k, v in dct.items())
|
|
39
34
|
|
|
35
|
+
@staticmethod
|
|
36
|
+
def is_dict_of_objects(dct: dict, typ: type, not_empty: bool = True) -> TypeGuard[dict]: # todo: Generic
|
|
37
|
+
if not_empty and not len(dct):
|
|
38
|
+
return False
|
|
39
|
+
return all(isinstance(k, int | str) and isinstance(v, typ) for k, v in dct.items())
|
|
40
|
+
|
|
40
41
|
@staticmethod
|
|
41
42
|
def is_list_of_dicts(lst: ListOfDicts, not_empty: bool = True) -> TypeGuard[ListOfDicts]:
|
|
42
43
|
if not_empty and not len(lst):
|
|
43
44
|
return False
|
|
44
45
|
return all(isinstance(el, dict) for el in lst)
|
|
45
46
|
|
|
47
|
+
@staticmethod
|
|
48
|
+
def is_list_of_objects(lst: list, typ: type, not_empty: bool = True) -> TypeGuard[list]:
|
|
49
|
+
if not_empty and not len(lst):
|
|
50
|
+
return False
|
|
51
|
+
return all(isinstance(el, typ) for el in lst)
|
|
52
|
+
|
|
46
53
|
@staticmethod
|
|
47
54
|
def is_flat_dict(dct: FlatDict, not_empty: bool = True) -> TypeGuard[FlatDict]:
|
|
48
55
|
if not_empty and not len(dct):
|
|
@@ -2,10 +2,10 @@ import logging
|
|
|
2
2
|
import re
|
|
3
3
|
from abc import abstractmethod
|
|
4
4
|
|
|
5
|
-
from
|
|
5
|
+
from xync_schema.pydantic import AdPydIn, PmPyd, BaseAd
|
|
6
6
|
from xync_schema.models import Ex, Coin, Cur, Pm, Pmex, Curex, Pmcur, Pmcurex, Coinex, PmexBank, Ad
|
|
7
7
|
|
|
8
|
-
from xync_client.Abc.Base import BaseClient, DictOfDicts, FlatDict,
|
|
8
|
+
from xync_client.Abc.Base import BaseClient, DictOfDicts, FlatDict, MapOfIdsList
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class BaseExClient(BaseClient):
|
|
@@ -33,7 +33,7 @@ class BaseExClient(BaseClient):
|
|
|
33
33
|
|
|
34
34
|
# 20: Список платежных методов
|
|
35
35
|
@abstractmethod
|
|
36
|
-
async def pms(self, cur: Cur = None) -> dict[int | str,
|
|
36
|
+
async def pms(self, cur: Cur = None) -> dict[int | str, PmPyd]: # {pm.exid: pm}
|
|
37
37
|
...
|
|
38
38
|
|
|
39
39
|
# 21: Список платежных методов по каждой валюте
|
|
@@ -54,9 +54,17 @@ class BaseExClient(BaseClient):
|
|
|
54
54
|
@abstractmethod
|
|
55
55
|
async def ads(
|
|
56
56
|
self, coin_exid: str, cur_exid: str, is_sell: bool, pm_exids: list[str | int] = None, amount: int = None
|
|
57
|
-
) ->
|
|
57
|
+
) -> list[BaseAd]: # {ad.id: ad}
|
|
58
58
|
...
|
|
59
59
|
|
|
60
|
+
# 42: Объява по id
|
|
61
|
+
@abstractmethod
|
|
62
|
+
async def ad(self, ad_id: int) -> BaseAd: ...
|
|
63
|
+
|
|
64
|
+
# Преобразрование объекта объявления из формата биржи в формат xync
|
|
65
|
+
@abstractmethod
|
|
66
|
+
async def _ad_epyd2pydin(self, ad: BaseAd) -> AdPydIn: ...
|
|
67
|
+
|
|
60
68
|
def _pmnorm(self, s: str) -> str:
|
|
61
69
|
def get_and_remove_acro(title: str) -> str:
|
|
62
70
|
acr = "".join(word[0] for word in title.split(" ") if len(word) > 1 and word.istitle())
|
|
@@ -117,9 +125,18 @@ class BaseExClient(BaseClient):
|
|
|
117
125
|
s = remove(rm_rgxps, s, True)
|
|
118
126
|
return s.replace(" ", "")
|
|
119
127
|
|
|
128
|
+
# 42: Минимальные объемы валют в объявлении
|
|
129
|
+
@abstractmethod
|
|
130
|
+
async def cur_mins(self) -> FlatDict: ...
|
|
131
|
+
|
|
132
|
+
# 43: Минимальные объемы монет в объявлении
|
|
133
|
+
@abstractmethod
|
|
134
|
+
async def coin_mins(self) -> FlatDict: ...
|
|
135
|
+
|
|
136
|
+
# Импорт Pm-ов (с Pmcur-, Pmex- и Pmcurex-ами) и валют (с Curex-ами) с биржи в бд
|
|
120
137
|
async def set_pmcurexs(self):
|
|
121
138
|
# Pms
|
|
122
|
-
pms_epyds: dict[int | str,
|
|
139
|
+
pms_epyds: dict[int | str, PmPyd] = {
|
|
123
140
|
k: v for k, v in sorted((await self.pms()).items(), key=lambda x: x[1].name)
|
|
124
141
|
} # sort by name
|
|
125
142
|
pms: dict[int | str, Pm] = dict({})
|
|
@@ -129,11 +146,9 @@ class BaseExClient(BaseClient):
|
|
|
129
146
|
if prev[1:] == (norm, pm.name):
|
|
130
147
|
logging.warning(f"Pm: '{pm.name}' duplicated with ids {prev[0]}: {k} on {self.ex.name}")
|
|
131
148
|
pm_ = pms.get(prev[0], (await Pm.get_or_none(name=prev[2])) or await Pm.get_or_none(identifier=prev[1]))
|
|
132
|
-
await Pmex.update_or_create({"pm": pm_}, ex=self.ex, exid=k
|
|
149
|
+
await Pmex.update_or_create({"pm": pm_, "name": pm.name}, ex=self.ex, exid=k)
|
|
133
150
|
elif prev[1] == norm:
|
|
134
|
-
logging.error(
|
|
135
|
-
f"Pm: '{pm.name}' & '{prev[2]}' overnormd as '{norm}' with ids {prev[0]}: {k} on {self.ex.name}"
|
|
136
|
-
)
|
|
151
|
+
logging.error(f"Pm: {pm.name}&{prev[2]} overnormd as {norm} with ids {prev[0]}: {k} on {self.ex.name}")
|
|
137
152
|
await Pmex.update_or_create(
|
|
138
153
|
{"pm": pms.get(prev[0], await Pm.get(name=prev[2]))}, ex=self.ex, exid=k, name=pm.name
|
|
139
154
|
)
|
|
@@ -146,16 +161,17 @@ class BaseExClient(BaseClient):
|
|
|
146
161
|
# Pmex banks
|
|
147
162
|
for k, pm in pms_epyds.items():
|
|
148
163
|
if banks := pm.banks:
|
|
149
|
-
pmex = await Pmex.get(
|
|
164
|
+
pmex = await Pmex.get(ex=self.ex, exid=k) # pm=pms[k],
|
|
150
165
|
for b in banks:
|
|
151
|
-
await PmexBank.update_or_create({"name": b.name}, exid=b.
|
|
166
|
+
await PmexBank.update_or_create({"name": b.name}, exid=b.exid, pmex=pmex)
|
|
152
167
|
|
|
153
168
|
# Curs
|
|
154
169
|
cursd = await self.curs()
|
|
155
170
|
curs: {int: Cur} = {k: (await Cur.update_or_create(ticker=c))[0] for k, c in cursd.items()}
|
|
156
171
|
# Curex
|
|
157
|
-
|
|
158
|
-
|
|
172
|
+
cur_mins = await self.cur_mins()
|
|
173
|
+
curexs = [Curex(cur=c, ex=self.ex, exid=k, minimum=cur_mins[k]) for k, c in curs.items()] # , p2p=True
|
|
174
|
+
await Curex.bulk_create(curexs, update_fields=["minimum"], on_conflict=["cur_id", "ex_id"])
|
|
159
175
|
|
|
160
176
|
cur2pms = await self.cur_pms_map()
|
|
161
177
|
# # Link PayMethods with currencies
|
|
@@ -173,12 +189,17 @@ class BaseExClient(BaseClient):
|
|
|
173
189
|
pmcurexs = [Pmcurex(pmcur=pmcur, ex=self.ex) for pmcur in pmcurs]
|
|
174
190
|
await Pmcurex.bulk_create(pmcurexs)
|
|
175
191
|
|
|
192
|
+
# Импорт монет (с Coinex-ами) с биржи в бд
|
|
176
193
|
async def set_coinexs(self):
|
|
177
194
|
res = await self.coins()
|
|
178
195
|
coins: dict[int, Coin] = {k: (await Coin.update_or_create(ticker=c))[0] for k, c in res.items()}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
196
|
+
coin_mins = await self.coin_mins()
|
|
197
|
+
coinexs: list[Coinex] = [Coinex(coin=c, ex=self.ex, exid=k, minimum=coin_mins[k]) for k, c in coins.items()]
|
|
198
|
+
await Coinex.bulk_create(coinexs, update_fields=["minimum"], on_conflict=["coin_id", "ex_id"])
|
|
199
|
+
|
|
200
|
+
# Сохранение чужого объявления (с Pm-ами) в бд
|
|
201
|
+
async def set_ad(self, ad: BaseAd) -> Ad:
|
|
202
|
+
adx = await self._ad_epyd2pydin(ad)
|
|
203
|
+
ad_db, _ = await Ad.update_or_create(adx.model_dump(exclude_none=True), id=adx.id)
|
|
204
|
+
await ad_db.pms.add(*adx.payMeths)
|
|
184
205
|
return ad_db
|
|
@@ -72,8 +72,8 @@ class ExClient(BaseExClient):
|
|
|
72
72
|
result.append(
|
|
73
73
|
{
|
|
74
74
|
"price": float(slot["priceValue"]),
|
|
75
|
-
"
|
|
76
|
-
"
|
|
75
|
+
"min_fiat": float(slot["minAmount"]),
|
|
76
|
+
"max_fiat": float(min(slot["maxAmount"], slot["amount"])),
|
|
77
77
|
"user": int(slot["userId"]) if slot["userId"] else None,
|
|
78
78
|
"pms": [int(pay_method["paymethodId"]) for pay_method in slot["paymethodInfo"]],
|
|
79
79
|
}
|
|
@@ -2,19 +2,10 @@ from asyncio import run
|
|
|
2
2
|
from enum import StrEnum
|
|
3
3
|
|
|
4
4
|
from x_model import init_db, HTTPException, FailReason
|
|
5
|
+
from xync_client.pyd import FiatXpyd
|
|
5
6
|
from xync_schema import models
|
|
6
7
|
|
|
7
|
-
from xync_client.TgWallet.pyd import
|
|
8
|
-
Banks,
|
|
9
|
-
FiatEpyd,
|
|
10
|
-
Attrs,
|
|
11
|
-
AttrsV2,
|
|
12
|
-
MyAdEPydSale,
|
|
13
|
-
MyAdEPydPurchase,
|
|
14
|
-
AdEpydInPurchase,
|
|
15
|
-
AdEpydInSale,
|
|
16
|
-
AdEPyd,
|
|
17
|
-
)
|
|
8
|
+
from xync_client.TgWallet.pyd import Banks, FiatEpyd, Attrs, AttrsV2, MyAdInPurchaseEpyd, MyAdInSaleEpyd, AdFullEpyd
|
|
18
9
|
from xync_client.loader import PG_DSN
|
|
19
10
|
from xync_schema.enums import AdStatus
|
|
20
11
|
|
|
@@ -25,7 +16,6 @@ from xync_schema.pydantic import FiatNew
|
|
|
25
16
|
|
|
26
17
|
from xync_client.Abc.Agent import BaseAgentClient
|
|
27
18
|
from xync_client.TgWallet.ex import ExClient
|
|
28
|
-
from xync_client.pyd import FiatXn
|
|
29
19
|
|
|
30
20
|
|
|
31
21
|
class Exceptions(StrEnum):
|
|
@@ -50,11 +40,6 @@ class AgentClient(BaseAgentClient, AuthClient):
|
|
|
50
40
|
)
|
|
51
41
|
return order["data"]
|
|
52
42
|
|
|
53
|
-
# 0: Получение ордера по ид
|
|
54
|
-
async def settings(self) -> ListOfDicts:
|
|
55
|
-
settings = await self._post("/p2p/public-api/v2/offer/settings/get")
|
|
56
|
-
return settings["data"]
|
|
57
|
-
|
|
58
43
|
# 0: Получение ордера по ид
|
|
59
44
|
async def order(self, oid) -> ListOfDicts:
|
|
60
45
|
orders = await self._post("/p2p/public-api/v2/offer/order/get", {"orderId": oid})
|
|
@@ -64,8 +49,8 @@ class AgentClient(BaseAgentClient, AuthClient):
|
|
|
64
49
|
async def order_request(self, ad_id: int, amount: float) -> dict | bool:
|
|
65
50
|
await self.agent.fetch_related("ex", "ex__agents")
|
|
66
51
|
ex_client: ExClient = self.agent.ex.client()
|
|
67
|
-
ad:
|
|
68
|
-
fiats = await self.
|
|
52
|
+
ad: AdFullEpyd = await ex_client.ad(ad_id=ad_id)
|
|
53
|
+
fiats = await self.fiats()
|
|
69
54
|
fiats_pms = {fiat["paymentMethod"]["code"]: fiat["id"] for fiat in fiats.values()}
|
|
70
55
|
if not (pms := ad.get("paymentMethods")):
|
|
71
56
|
print(ad)
|
|
@@ -128,18 +113,18 @@ class AgentClient(BaseAgentClient, AuthClient):
|
|
|
128
113
|
}
|
|
129
114
|
|
|
130
115
|
# 25: Список реквизитов моих платежных методов
|
|
131
|
-
async def fiats(self
|
|
116
|
+
async def fiats(self) -> list[FiatEpyd]:
|
|
132
117
|
resp = await self._post("/p2p/public-api/v3/payment-details/get/by-user-id")
|
|
133
118
|
return [FiatEpyd(**fiat) for fiat in resp["data"]]
|
|
134
119
|
|
|
135
|
-
async def fiat_epyd2xpyd(self, fiat: FiatEpyd) ->
|
|
120
|
+
async def fiat_epyd2xpyd(self, fiat: FiatEpyd) -> FiatXpyd:
|
|
136
121
|
if not (pmex := await Pmex.get_or_none(exid=fiat.paymentMethod.code, ex=self.agent.ex)):
|
|
137
122
|
raise HTTPException(FailReason.body, f"No Pmex {fiat.paymentMethod.code} on ex#{self.agent.ex.name}", 404)
|
|
138
123
|
if not (pmcur := await Pmcur.get_or_none(cur__ticker=fiat.currency, pm_id=pmex.pm_id)):
|
|
139
124
|
raise HTTPException(
|
|
140
125
|
FailReason.body, f"No Pmcur with cur#{fiat.currency} and pm#{fiat.paymentMethod.code}", 404
|
|
141
126
|
)
|
|
142
|
-
ftx =
|
|
127
|
+
ftx = FiatXpyd(
|
|
143
128
|
id=fiat.id,
|
|
144
129
|
detail="",
|
|
145
130
|
name=fiat.name,
|
|
@@ -232,7 +217,7 @@ class AgentClient(BaseAgentClient, AuthClient):
|
|
|
232
217
|
)
|
|
233
218
|
return (
|
|
234
219
|
[
|
|
235
|
-
|
|
220
|
+
MyAdEpydSale(**ad) if ad["type"] == "SALE" else MyAdEpydPurchase(**ad)
|
|
236
221
|
for ad in ads["data"]
|
|
237
222
|
if not status or (status and ad["status"] == mapping[status])
|
|
238
223
|
]
|
|
@@ -241,7 +226,7 @@ class AgentClient(BaseAgentClient, AuthClient):
|
|
|
241
226
|
)
|
|
242
227
|
|
|
243
228
|
# 30: Создание объявления
|
|
244
|
-
async def ad_new(self, ad:
|
|
229
|
+
async def ad_new(self, ad: MyAdInPurchaseEpyd | MyAdInSaleEpyd) -> Ad:
|
|
245
230
|
# coin: Coin,
|
|
246
231
|
# cur: str,
|
|
247
232
|
# is_sell: bool,
|
|
@@ -255,7 +240,7 @@ class AgentClient(BaseAgentClient, AuthClient):
|
|
|
255
240
|
# status: AdStatus = AdStatus.active,
|
|
256
241
|
# ) -> Ad.pyd():
|
|
257
242
|
dct = {
|
|
258
|
-
"type":
|
|
243
|
+
"type": ad.type,
|
|
259
244
|
"initVolume": {"currencyCode": coin, "amount": amount},
|
|
260
245
|
"orderRoundingRequired": True,
|
|
261
246
|
"price": {
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
from asyncio import run
|
|
2
|
+
|
|
2
3
|
from x_model import init_db
|
|
3
|
-
from
|
|
4
|
+
from xync_schema.pydantic import AdPydIn, PmPyd, PmexBankPyd
|
|
4
5
|
|
|
5
6
|
from xync_schema import models
|
|
6
|
-
from xync_schema.models import Ex, Agent, Direction, Pair, Coin, Cur
|
|
7
|
+
from xync_schema.models import Ex, Agent, Direction, Pair, Coin, Cur, Pm
|
|
7
8
|
|
|
8
|
-
from xync_client.TgWallet.pyd import AdFullEpyd, AdEpyd
|
|
9
|
+
from xync_client.TgWallet.pyd import AdFullEpyd, AdEpyd, PmEpydRoot
|
|
9
10
|
from xync_client.loader import PG_DSN
|
|
10
11
|
from xync_client.Abc.Ex import BaseExClient
|
|
11
|
-
from xync_client.Abc.Base import FlatDict,
|
|
12
|
+
from xync_client.Abc.Base import FlatDict, MapOfIdsList
|
|
12
13
|
from xync_client.TgWallet.auth import AuthClient
|
|
13
14
|
|
|
14
15
|
|
|
@@ -17,23 +18,42 @@ class ExClient(BaseExClient, AuthClient):
|
|
|
17
18
|
self.agent: Agent = [ag for ag in ex.agents if ag.auth][0] # need for AuthTrait
|
|
18
19
|
super().__init__(ex) # , "host_p2p"
|
|
19
20
|
|
|
21
|
+
# 00: todo: min-max for cur and coin ad amount, order, fee ..
|
|
22
|
+
async def _settings(self) -> dict:
|
|
23
|
+
settings = await self._post("/p2p/public-api/v2/offer/settings/get")
|
|
24
|
+
return settings["data"]
|
|
25
|
+
|
|
26
|
+
async def cur_mins(self) -> FlatDict:
|
|
27
|
+
stg = await self._settings()
|
|
28
|
+
return stg["offerSettings"]["minOrderAmountByCurrencyCode"]
|
|
29
|
+
|
|
30
|
+
async def coin_mins(self) -> FlatDict:
|
|
31
|
+
stg = await self._settings()
|
|
32
|
+
lims = list(stg["offerSettings"]["offerVolumeLimitsPerMarket"].values())
|
|
33
|
+
coins = {k: max(float(v[k]["minInclusive"]) for v in lims) for k, v in lims[0].items()}
|
|
34
|
+
return coins
|
|
35
|
+
|
|
20
36
|
# 19: Список поддерживаемых валют тейкера
|
|
21
37
|
async def curs(self) -> FlatDict:
|
|
22
38
|
coins_curs = await self._post("/p2p/public-api/v2/currency/all-supported")
|
|
23
39
|
return {c["code"]: c["code"] for c in coins_curs["data"]["fiat"]}
|
|
24
40
|
|
|
25
|
-
async def _pms(self, cur: str) -> dict[str,
|
|
41
|
+
async def _pms(self, cur: str) -> dict[str, PmEpydRoot]:
|
|
26
42
|
pms = await self._post("/p2p/public-api/v3/payment-details/get-methods/by-currency-code", {"currencyCode": cur})
|
|
27
|
-
return {pm["code"]:
|
|
43
|
+
return {pm["code"]: PmEpydRoot(**pm) for pm in pms["data"]}
|
|
28
44
|
|
|
29
|
-
# 20: Список платежных
|
|
30
|
-
async def pms(self, cur: str = None) ->
|
|
45
|
+
# 20: Список платежных методов. todo: refact to pmexs?
|
|
46
|
+
async def pms(self, cur: str = None) -> dict[str, PmPyd]:
|
|
47
|
+
pms: dict[str:PmEpydRoot] = {}
|
|
31
48
|
if cur:
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return
|
|
49
|
+
pms = await self._pms(cur)
|
|
50
|
+
else:
|
|
51
|
+
for cur in await self.curs():
|
|
52
|
+
pms |= await self._pms(cur)
|
|
53
|
+
return {
|
|
54
|
+
k: PmPyd(name=pm.nameEng, banks=[PmexBankPyd(exid=b.code, name=b.name) for b in pm.banks or []])
|
|
55
|
+
for k, pm in pms.items()
|
|
56
|
+
}
|
|
37
57
|
|
|
38
58
|
# 21: Список платежных методов по каждой валюте
|
|
39
59
|
async def cur_pms_map(self) -> MapOfIdsList:
|
|
@@ -51,9 +71,10 @@ class ExClient(BaseExClient, AuthClient):
|
|
|
51
71
|
pairs = {cur: set(coins.values()) for cur in curs.values()}
|
|
52
72
|
return pairs
|
|
53
73
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
74
|
+
# 42: Объява по id
|
|
75
|
+
async def ad(self, ad_id: int) -> AdFullEpyd:
|
|
76
|
+
ad = await self._post("/p2p/public-api/v2/offer/get", {"offerId": ad_id})
|
|
77
|
+
return AdFullEpyd(**ad["data"])
|
|
57
78
|
|
|
58
79
|
# 24: Список объяв по (buy/sell, cur, coin, pm)
|
|
59
80
|
async def ads(
|
|
@@ -70,39 +91,42 @@ class ExClient(BaseExClient, AuthClient):
|
|
|
70
91
|
ads = await self._post("/p2p/public-api/v2/offer/depth-of-market/", params, "data")
|
|
71
92
|
return [AdEpyd(**ad) for ad in ads]
|
|
72
93
|
|
|
73
|
-
async def
|
|
94
|
+
async def _ad_epyd2pydin(self, ad: AdEpyd | AdFullEpyd) -> AdPydIn:
|
|
74
95
|
coin = await Coin.get_or_create_by_name(ad.price.baseCurrencyCode)
|
|
75
96
|
cur = await Cur.get_or_create_by_name(ad.price.quoteCurrencyCode)
|
|
76
97
|
pair, _ = await Pair.get_or_create(coin=coin, cur=cur, ex=self.ex)
|
|
77
98
|
dr, _ = await Direction.get_or_create(pair=pair, sell=ad.is_sell)
|
|
78
99
|
maker, _ = await Agent.get_or_create(exid=ad.user.userId, ex=self.ex)
|
|
79
|
-
|
|
100
|
+
|
|
101
|
+
adx = AdPydIn(
|
|
80
102
|
id=ad.id,
|
|
81
103
|
price=ad.price.value,
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
104
|
+
min_fiat=ad.orderAmountLimits.min,
|
|
105
|
+
max_fiat=ad.orderAmountLimits.max,
|
|
106
|
+
direction=dr,
|
|
107
|
+
agent=maker,
|
|
86
108
|
detail=getattr(ad, "comment", None),
|
|
109
|
+
payMeths=await Pm.filter(pmexs__ex=self.agent.ex, pmexs__exid__in=[p.code for p in ad.paymentMethods]),
|
|
110
|
+
# todo: maybe later adpm_banks
|
|
87
111
|
)
|
|
88
112
|
return adx
|
|
89
113
|
|
|
90
114
|
|
|
91
|
-
async def
|
|
115
|
+
async def _test():
|
|
92
116
|
await init_db(PG_DSN, models, True)
|
|
93
117
|
tgex = await Ex.get(name="TgWallet").prefetch_related("agents", "agents__ex")
|
|
94
118
|
cl: ExClient = tgex.client()
|
|
119
|
+
await cl.pms("RUB")
|
|
95
120
|
await cl.set_pmcurexs()
|
|
96
121
|
await cl.set_coinexs()
|
|
97
122
|
ads: list[AdEpyd] = await cl.ads("USDT", "RUB", False)
|
|
98
|
-
ad: AdFullEpyd = await cl.
|
|
99
|
-
|
|
100
|
-
await cl.
|
|
123
|
+
ad: AdFullEpyd = await cl.ad(ads[0].id)
|
|
124
|
+
await cl.set_ad(ad)
|
|
125
|
+
ads: list[AdEpyd] = await cl.ads("USDT", "RUB", True)
|
|
101
126
|
ad: AdEpyd = ads[1]
|
|
102
|
-
|
|
103
|
-
await cl.set_ad(adx)
|
|
127
|
+
await cl.set_ad(ad)
|
|
104
128
|
await cl.close()
|
|
105
129
|
|
|
106
130
|
|
|
107
131
|
if __name__ == "__main__":
|
|
108
|
-
run(
|
|
132
|
+
run(_test())
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import Literal
|
|
2
2
|
from pydantic import BaseModel
|
|
3
|
-
from
|
|
3
|
+
from xync_schema.pydantic import BaseAd
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class UserStatistics(BaseModel):
|
|
@@ -100,6 +100,17 @@ class AttrsV2(AttrsV2In):
|
|
|
100
100
|
values: list[KeyVal | Banks]
|
|
101
101
|
|
|
102
102
|
|
|
103
|
+
class PmEpyd(BaseModel):
|
|
104
|
+
code: str
|
|
105
|
+
name: str
|
|
106
|
+
originNameLocale: str
|
|
107
|
+
nameEng: str
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class PmEpydRoot(PmEpyd):
|
|
111
|
+
banks: list[PmEpyd] | None = None
|
|
112
|
+
|
|
113
|
+
|
|
103
114
|
class FiatPydIn(BaseModel):
|
|
104
115
|
paymentMethodCode: str
|
|
105
116
|
currencyCode: str
|
|
@@ -110,7 +121,7 @@ class FiatPydIn(BaseModel):
|
|
|
110
121
|
class FiatEpyd(BaseModel):
|
|
111
122
|
id: int
|
|
112
123
|
userId: int
|
|
113
|
-
paymentMethod:
|
|
124
|
+
paymentMethod: PmEpydRoot
|
|
114
125
|
currency: str
|
|
115
126
|
name: str = ""
|
|
116
127
|
attributes: Attrs | AttrsV2
|
|
@@ -122,17 +133,16 @@ class InitVolume(BaseModel):
|
|
|
122
133
|
|
|
123
134
|
|
|
124
135
|
class _PaymentMethodsTrait:
|
|
125
|
-
paymentMethods: list[
|
|
136
|
+
paymentMethods: list[PmEpydRoot]
|
|
126
137
|
|
|
127
138
|
|
|
128
|
-
class __BaseCommonAd(
|
|
129
|
-
id: int | None = None
|
|
139
|
+
class __BaseCommonAd(BaseAd):
|
|
130
140
|
type: Literal["PURCHASE", "SALE"]
|
|
131
141
|
price: Price
|
|
132
142
|
|
|
133
143
|
|
|
134
144
|
class _MyAdEpydIn(__BaseCommonAd):
|
|
135
|
-
|
|
145
|
+
orderConfirmationTimeout: Literal["PT3M", "PT15M"]
|
|
136
146
|
comment: str
|
|
137
147
|
initVolume: InitVolume
|
|
138
148
|
orderRoundingRequired: bool
|
|
@@ -167,7 +177,7 @@ class AdFullEpyd(AdEpyd):
|
|
|
167
177
|
status: Literal["ACTIVE", "INACTIVE", "ACTIVATING"]
|
|
168
178
|
createDateTime: str
|
|
169
179
|
comment: str
|
|
170
|
-
orderConfirmationTimeout: Literal["PT3M"]
|
|
180
|
+
orderConfirmationTimeout: Literal["PT3M", "PT15M"]
|
|
171
181
|
orderAcceptTimeout: Literal["PT10M"]
|
|
172
182
|
|
|
173
183
|
|
|
@@ -19,7 +19,6 @@ tests/_todo_refact/Wallet/test_agent.py
|
|
|
19
19
|
tests/_todo_refact/Wallet/test_ex.py
|
|
20
20
|
xync_client/__init__.py
|
|
21
21
|
xync_client/loader.py
|
|
22
|
-
xync_client/pyd.py
|
|
23
22
|
xync_client.egg-info/PKG-INFO
|
|
24
23
|
xync_client.egg-info/SOURCES.txt
|
|
25
24
|
xync_client.egg-info/dependency_links.txt
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
from pydantic import BaseModel, model_validator
|
|
2
|
-
from xync_schema.enums import AdStatus
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class PayMeth(BaseModel):
|
|
6
|
-
code: str
|
|
7
|
-
name: str
|
|
8
|
-
originNameLocale: str
|
|
9
|
-
nameEng: str
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class PmXpyd(BaseModel):
|
|
13
|
-
id: int | None = None
|
|
14
|
-
name: str
|
|
15
|
-
logo: str | None = None
|
|
16
|
-
banks: list[PayMeth] | None = None # todo: refact excess data in banks
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class PmcurXpyd(BaseModel):
|
|
20
|
-
pm_id: int
|
|
21
|
-
cur_id: int
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class FiatXpyd(BaseModel):
|
|
25
|
-
# unq
|
|
26
|
-
id: int = None
|
|
27
|
-
user_id: int
|
|
28
|
-
pmcur_id: int | None = None
|
|
29
|
-
pmcur: PmcurXpyd | None = None
|
|
30
|
-
# df
|
|
31
|
-
detail: str
|
|
32
|
-
name: str = ""
|
|
33
|
-
amount: float
|
|
34
|
-
target: float | None = None
|
|
35
|
-
|
|
36
|
-
banks: list[str] = []
|
|
37
|
-
|
|
38
|
-
@classmethod
|
|
39
|
-
@model_validator(mode="before")
|
|
40
|
-
def check_at_least_one_field(cls, values):
|
|
41
|
-
if values.get("pmcur") or values.get("pmcur_id"):
|
|
42
|
-
return values
|
|
43
|
-
raise ValueError("pmcur_id or pmcur is required")
|
|
44
|
-
|
|
45
|
-
def args(self) -> tuple[dict, dict]:
|
|
46
|
-
unq: tuple[str, ...] = "id", "user_id", "pmcur_id", "pmcur"
|
|
47
|
-
df: tuple[str, ...] = "detail", "name", "amount", "target"
|
|
48
|
-
|
|
49
|
-
d = self.model_dump()
|
|
50
|
-
return {k: getattr(self, k) for k in df if d.get(k)}, {k: getattr(self, k) for k in unq if d.get(k)}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
class AdInXpyd(BaseModel):
|
|
54
|
-
# unq
|
|
55
|
-
id: int
|
|
56
|
-
# df
|
|
57
|
-
price: float
|
|
58
|
-
minFiat: float
|
|
59
|
-
maxFiat: float | None = None
|
|
60
|
-
detail: str | None = None
|
|
61
|
-
autoMsg: str | None = None
|
|
62
|
-
status: AdStatus = AdStatus.active
|
|
63
|
-
agent_id: int
|
|
64
|
-
direction_id: int
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
class FiatexXpyd(BaseModel):
|
|
68
|
-
id: int | None = None
|
|
69
|
-
exid: str
|
|
70
|
-
ex_id: int
|
|
71
|
-
fiat_id: int
|
|
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.25.dev0 → xync_client-0.0.25.dev4}/tests/_todo_refact/Binance/test_binance.py
RENAMED
|
File without changes
|
|
File without changes
|
{xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/tests/_todo_refact/Bybit/test_bybit_p2p.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
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
|
{xync_client-0.0.25.dev0 → xync_client-0.0.25.dev4}/xync_client.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|