xync-client 0.0.164__py3-none-any.whl → 0.0.179.dev4__py3-none-any.whl
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/Abc/Agent.py +154 -30
- xync_client/Abc/Ex.py +113 -136
- xync_client/Abc/Order.py +20 -17
- xync_client/Abc/xtype.py +139 -65
- xync_client/Binance/ex.py +2 -2
- xync_client/BingX/agent.py +1 -1
- xync_client/BingX/ex.py +2 -2
- xync_client/BitGet/agent.py +1 -3
- xync_client/BitGet/ex.py +10 -9
- xync_client/BitPapa/ex.py +12 -9
- xync_client/Bybit/agent.py +106 -349
- xync_client/Bybit/etype/ad.py +79 -58
- xync_client/Bybit/etype/cred.py +25 -3
- xync_client/Bybit/etype/order.py +148 -92
- xync_client/Bybit/ex.py +27 -15
- xync_client/Bybit/{InAgent.py → inAgent.py} +5 -10
- xync_client/Bybit/order.py +42 -16
- xync_client/Gate/ex.py +2 -2
- xync_client/Htx/agent.py +13 -16
- xync_client/Htx/etype/ad.py +2 -4
- xync_client/Htx/etype/test.py +4 -4
- xync_client/Htx/ex.py +37 -5
- xync_client/KuCoin/ex.py +2 -2
- xync_client/Mexc/agent.py +11 -13
- xync_client/Mexc/ex.py +5 -5
- xync_client/Okx/agent.py +3 -9
- xync_client/Okx/ex.py +11 -10
- xync_client/TgWallet/agent.py +21 -21
- xync_client/TgWallet/ex.py +15 -15
- xync_client/TgWallet/pyd.py +5 -5
- xync_client/pm_unifier.py +3 -2
- {xync_client-0.0.164.dist-info → xync_client-0.0.179.dev4.dist-info}/METADATA +1 -1
- {xync_client-0.0.164.dist-info → xync_client-0.0.179.dev4.dist-info}/RECORD +35 -35
- {xync_client-0.0.164.dist-info → xync_client-0.0.179.dev4.dist-info}/WHEEL +0 -0
- {xync_client-0.0.164.dist-info → xync_client-0.0.179.dev4.dist-info}/top_level.txt +0 -0
xync_client/Abc/Agent.py
CHANGED
|
@@ -5,49 +5,53 @@ from collections import defaultdict
|
|
|
5
5
|
from typing import Literal
|
|
6
6
|
|
|
7
7
|
from pydantic import BaseModel
|
|
8
|
-
from
|
|
8
|
+
from tortoise.exceptions import IntegrityError
|
|
9
9
|
from x_client import df_hdrs
|
|
10
10
|
from x_client.aiohttp import Client as HttpClient
|
|
11
|
-
from xync_bot import XyncBot
|
|
12
11
|
from xync_client.Abc.PmAgent import PmAgentClient
|
|
13
12
|
|
|
14
13
|
from xync_client.Abc.InAgent import BaseInAgentClient
|
|
15
14
|
|
|
16
15
|
from xync_client.Bybit.etype.order import TakeAdReq
|
|
17
16
|
from xync_schema import models
|
|
18
|
-
from xync_schema.models import OrderStatus, Coin, Cur, Ad,
|
|
19
|
-
from xync_schema
|
|
17
|
+
from xync_schema.models import OrderStatus, Coin, Cur, Ad, Actor, Agent
|
|
18
|
+
from xync_schema import xtype
|
|
20
19
|
|
|
21
20
|
from xync_client.Abc.Ex import BaseExClient
|
|
22
|
-
from xync_client.Abc.xtype import
|
|
21
|
+
from xync_client.Abc.xtype import (
|
|
22
|
+
BaseCredEx,
|
|
23
|
+
BaseOrderReq,
|
|
24
|
+
BaseAd,
|
|
25
|
+
AdUpdReq,
|
|
26
|
+
GetAdsReq,
|
|
27
|
+
BaseCredexsExidsTrait,
|
|
28
|
+
BaseOrderFull,
|
|
29
|
+
)
|
|
23
30
|
from xync_client.Gmail import GmClient
|
|
24
31
|
|
|
25
32
|
|
|
26
|
-
class BaseAgentClient(HttpClient, BaseInAgentClient):
|
|
33
|
+
class BaseAgentClient(HttpClient, BaseInAgentClient): # , metaclass=ABCMeta
|
|
27
34
|
actor: Actor
|
|
28
35
|
agent: Agent
|
|
29
|
-
bbot: XyncBot
|
|
30
|
-
fbot: FileClient
|
|
31
36
|
ex_client: BaseExClient
|
|
32
|
-
orders: dict[int, tuple[models.Order,
|
|
37
|
+
orders: dict[int, tuple[models.Order, xtype.BaseOrder]] = {} # pending
|
|
33
38
|
pm_clients: dict[int, PmAgentClient] # {pm_id: PmAgentClient}
|
|
34
39
|
api: HttpClient
|
|
35
40
|
cred_x2e: dict[int, int] = {}
|
|
36
|
-
cred_e2x: dict[int,
|
|
41
|
+
cred_e2x: dict[int, models.CredEx] = {}
|
|
42
|
+
order_x2e: dict[int, int] = {}
|
|
43
|
+
order_e2x: dict[int, int] = {}
|
|
44
|
+
cdx_cls: type[BaseCredEx]
|
|
37
45
|
|
|
38
46
|
def __init__(
|
|
39
47
|
self,
|
|
40
48
|
agent: Agent, # agent.actor.person.user
|
|
41
49
|
ex_client: BaseExClient,
|
|
42
|
-
fbot: FileClient,
|
|
43
|
-
bbot: XyncBot,
|
|
44
50
|
pm_clients: dict[int, PmAgentClient] = None,
|
|
45
51
|
headers: dict[str, str] = df_hdrs,
|
|
46
52
|
cookies: dict[str, str] = None,
|
|
47
53
|
proxy: models.Proxy = None,
|
|
48
54
|
):
|
|
49
|
-
self.bbot = bbot
|
|
50
|
-
self.fbot = fbot
|
|
51
55
|
self.agent: Agent = agent
|
|
52
56
|
self.actor: Actor = agent.actor
|
|
53
57
|
self.gmail = agent.actor.person.user.gmail and GmClient(agent.actor.person.user)
|
|
@@ -59,15 +63,30 @@ class BaseAgentClient(HttpClient, BaseInAgentClient):
|
|
|
59
63
|
|
|
60
64
|
async def x2e_cred(self, cred_id: int) -> int: # cred.exid
|
|
61
65
|
if not self.cred_x2e.get(cred_id):
|
|
62
|
-
|
|
63
|
-
self.
|
|
66
|
+
credex = await models.CredEx.get(cred_id=cred_id)
|
|
67
|
+
self.cred_x2e[cred_id] = credex.exid
|
|
68
|
+
self.cred_e2x[credex.exid] = credex
|
|
64
69
|
return self.cred_x2e[cred_id]
|
|
65
70
|
|
|
66
|
-
async def e2x_cred(self,
|
|
67
|
-
if not self.cred_e2x.get(exid):
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
async def e2x_cred(self, base_credex: BaseCredEx) -> models.CredEx: # cred.id
|
|
72
|
+
if not self.cred_e2x.get(base_credex.exid):
|
|
73
|
+
if not (credex := await models.CredEx.get_or_none(exid=base_credex.exid, ex=self.ex_client.ex)):
|
|
74
|
+
credex = await self.credex_save(base_credex)
|
|
75
|
+
self.cred_e2x[base_credex.exid] = credex
|
|
76
|
+
self.cred_x2e[credex.cred_id] = base_credex.exid
|
|
77
|
+
return self.cred_e2x[base_credex.exid]
|
|
78
|
+
|
|
79
|
+
async def x2e_order(self, order_id: int) -> int: # order.exid
|
|
80
|
+
if not self.order_x2e.get(order_id):
|
|
81
|
+
self.order_x2e[order_id] = (await models.Order[order_id]).exid
|
|
82
|
+
self.order_e2x[self.order_x2e[order_id]] = order_id
|
|
83
|
+
return self.order_x2e[order_id]
|
|
84
|
+
|
|
85
|
+
async def e2x_order(self, exid: int) -> int: # order.id
|
|
86
|
+
if not self.order_e2x.get(exid):
|
|
87
|
+
self.order_e2x[exid] = (await models.Order.get(exid=exid, taker__ex=self.ex_client.ex)).id
|
|
88
|
+
self.order_x2e[self.order_e2x[exid]] = exid
|
|
89
|
+
return self.order_e2x[exid]
|
|
71
90
|
|
|
72
91
|
async def start(self):
|
|
73
92
|
if self.agent.status & 1: # race
|
|
@@ -78,6 +97,115 @@ class BaseAgentClient(HttpClient, BaseInAgentClient):
|
|
|
78
97
|
if self.agent.status & 2: # listen
|
|
79
98
|
await self.start_listen()
|
|
80
99
|
|
|
100
|
+
@abstractmethod
|
|
101
|
+
async def _get_creds(self) -> list[BaseModel]: ...
|
|
102
|
+
|
|
103
|
+
async def get_creds(self) -> list[BaseCredEx]:
|
|
104
|
+
creds: list[BaseModel] = await self._get_creds()
|
|
105
|
+
return [self.cdx_cls.model_validate(cred, from_attributes=True) for cred in creds]
|
|
106
|
+
|
|
107
|
+
async def credex_save(self, cdx: BaseCredEx, pers_id: int = None, cur_id: int = None) -> models.CredEx | None:
|
|
108
|
+
pmex = None
|
|
109
|
+
if cred_old := await models.Cred.get_or_none(
|
|
110
|
+
credexs__exid=cdx.exid, credexs__ex=self.actor.ex
|
|
111
|
+
).prefetch_related("pmcur"): # is old Cred
|
|
112
|
+
cur_id = cur_id or cred_old.pmcur.cur_id
|
|
113
|
+
elif not cur_id: # is new Cred
|
|
114
|
+
if cdx.curex_exid:
|
|
115
|
+
cur_id = (await models.CurEx.get(exid=cdx.curex_exid, ex=self.actor.ex)).cur_id
|
|
116
|
+
else:
|
|
117
|
+
pmex = await models.PmEx.get_or_none(exid=cdx.pmex_exid, ex=self.ex_client.ex).prefetch_related(
|
|
118
|
+
"pm__curs"
|
|
119
|
+
)
|
|
120
|
+
cur_id = (
|
|
121
|
+
pmex.pm.df_cur_id
|
|
122
|
+
or (await cdx.guess_cur(pmex.pm.curs) if len(pmex.pm.curs) != 1 else pmex.pm.curs[0].cur_id)
|
|
123
|
+
or (pmex.pm.country_id and (await pmex.pm.country).cur_id)
|
|
124
|
+
# or (ecdx.currencyBalance and await models.Cur.get_or_none(ticker=ecdx.currencyBalance[0])) # это че еще за хуйня?
|
|
125
|
+
)
|
|
126
|
+
if not cur_id:
|
|
127
|
+
raise ValueError(f"Set default cur for {pmex.name}")
|
|
128
|
+
pm_id = pmex and pmex.pm_id or await self.ex_client.e2x_pm(cdx.pmex_exid)
|
|
129
|
+
if not (pmcur := await models.PmCur.get_or_none(cur_id=cur_id, pm_id=pm_id)):
|
|
130
|
+
raise ValueError(f"No PmCur with cur#{cur_id} and pm#{cdx.pmex_exid}", 404)
|
|
131
|
+
try:
|
|
132
|
+
pers_id = pers_id or cdx.seller.exid and (await self.ex_client.e2x_actor(cdx.seller)).person_id
|
|
133
|
+
cred_db, _ = await models.Cred.update_or_create(
|
|
134
|
+
{"name": cdx.name, "extra": cdx.extra},
|
|
135
|
+
pmcur=pmcur,
|
|
136
|
+
person_id=pers_id,
|
|
137
|
+
detail=cdx.detail,
|
|
138
|
+
)
|
|
139
|
+
if not cred_db.ovr_pm_id and ("XyncPay" in cred_db.detail or "XyncPay" in cred_db.extra):
|
|
140
|
+
cred_db.ovr_pm_id = 0
|
|
141
|
+
await cred_db.save()
|
|
142
|
+
credex_db, _ = await models.CredEx.update_or_create(exid=cdx.exid, cred=cred_db, ex=self.actor.ex)
|
|
143
|
+
except IntegrityError as e:
|
|
144
|
+
raise e
|
|
145
|
+
return credex_db
|
|
146
|
+
|
|
147
|
+
# 25: Список реквизитов моих платежных методов
|
|
148
|
+
async def load_creds(self) -> list[models.CredEx]:
|
|
149
|
+
credexs_epyd: list[BaseCredEx] = await self.get_creds()
|
|
150
|
+
credexs: list[models.CredEx] = [await self.credex_save(f) for f in credexs_epyd]
|
|
151
|
+
return credexs
|
|
152
|
+
|
|
153
|
+
async def my_ad_save(
|
|
154
|
+
self,
|
|
155
|
+
bmad: BaseAd | BaseCredexsExidsTrait,
|
|
156
|
+
rname: str = None,
|
|
157
|
+
) -> models.MyAd:
|
|
158
|
+
ad_db = await self.ex_client.ad_save(bmad)
|
|
159
|
+
mad_db, _ = await models.MyAd.update_or_create(ad=ad_db)
|
|
160
|
+
credexs = await models.CredEx.filter(ex_id=self.actor.ex_id, exid__in=bmad.credex_exids)
|
|
161
|
+
await mad_db.credexs.clear()
|
|
162
|
+
await mad_db.credexs.add(*credexs)
|
|
163
|
+
return mad_db
|
|
164
|
+
|
|
165
|
+
async def load_my_ads(self, only_active: bool = None) -> list[models.MyAd]: # upserted)
|
|
166
|
+
ads = await self.get_my_ads(True)
|
|
167
|
+
if not only_active:
|
|
168
|
+
ads += await self.get_my_ads(False)
|
|
169
|
+
return [await self.my_ad_save(ad) for ad in ads]
|
|
170
|
+
|
|
171
|
+
@abstractmethod
|
|
172
|
+
async def _get_order_full(self, order_exid: int) -> BaseOrderFull: ...
|
|
173
|
+
|
|
174
|
+
async def get_order_full(self, order_exid: int) -> xtype.BaseOrder:
|
|
175
|
+
eorder: BaseOrderFull = await self._get_order_full(order_exid)
|
|
176
|
+
_, cur_scale, __ = await self.ex_client.x2e_cur(await self.ex_client.e2x_cur(eorder.curex_exid))
|
|
177
|
+
_, coin_scale = await self.ex_client.x2e_coin(await self.ex_client.e2x_coin(eorder.coinex_exid))
|
|
178
|
+
ad = await self.ex_client.e2x_ad(eorder.ad_id)
|
|
179
|
+
credex = await self.e2x_cred(eorder.credex)
|
|
180
|
+
taker = await self.ex_client.e2x_actor(eorder.taker)
|
|
181
|
+
border = eorder.model_dump()
|
|
182
|
+
border.update(
|
|
183
|
+
ad_id=ad.id,
|
|
184
|
+
cred_id=credex.cred_id,
|
|
185
|
+
taker_id=taker.id,
|
|
186
|
+
amount=int(eorder.amount * 10**cur_scale),
|
|
187
|
+
quantity=int(eorder.quantity * 10**coin_scale),
|
|
188
|
+
)
|
|
189
|
+
return xtype.BaseOrder.model_validate(border)
|
|
190
|
+
|
|
191
|
+
async def load_order(self, order_exid: int, force_refresh: bool = False) -> tuple[models.Order, xtype.BaseOrder]:
|
|
192
|
+
if not self.orders.get(order_exid) or force_refresh:
|
|
193
|
+
order: xtype.BaseOrder = await self.get_order_full(order_exid)
|
|
194
|
+
if not (
|
|
195
|
+
order_db := await models.Order.get_or_none(
|
|
196
|
+
exid=order_exid, ad__maker__ex=self.actor.ex
|
|
197
|
+
).prefetch_related("ad__pair_side__pair", "cred__pmcur__cur")
|
|
198
|
+
):
|
|
199
|
+
order_db = await self.order_save(order)
|
|
200
|
+
self.orders[order_exid] = order_db, order
|
|
201
|
+
return self.orders[order_exid]
|
|
202
|
+
|
|
203
|
+
async def order_save(self, order: xtype.BaseOrder) -> models.Order:
|
|
204
|
+
order_in = models.Order.validate(order.model_dump())
|
|
205
|
+
odb, _ = await models.Order.update_or_create(**order_in.df_unq())
|
|
206
|
+
# await odb.fetch_related("ad") # todo: for what?
|
|
207
|
+
return odb
|
|
208
|
+
|
|
81
209
|
async def racing(self, race: models.Race):
|
|
82
210
|
pair = race.road.ad.pair_side.pair
|
|
83
211
|
taker_side: int = not race.road.ad.pair_side.is_sell
|
|
@@ -116,7 +244,7 @@ class BaseAgentClient(HttpClient, BaseInAgentClient):
|
|
|
116
244
|
asset = await models.Asset.get(addr__actor=self.actor, addr__coin_id=coinex.coin_id)
|
|
117
245
|
volume = asset.free * 10**-coinex.scale
|
|
118
246
|
volume = str(round(volume, coinex.scale))
|
|
119
|
-
get_ads_req =
|
|
247
|
+
get_ads_req = GetAdsReq(
|
|
120
248
|
coin_id=pair.coin_id, cur_id=pair.cur_id, is_sell=bool(taker_side), pm_ids=pm_ids, amount=amt, limit=50
|
|
121
249
|
)
|
|
122
250
|
try:
|
|
@@ -363,10 +491,6 @@ class BaseAgentClient(HttpClient, BaseInAgentClient):
|
|
|
363
491
|
self, exid: int | str, cur: str, detail: str, name: str, fid: int, typ: str, extra=None
|
|
364
492
|
) -> fiat_pyd: ...
|
|
365
493
|
|
|
366
|
-
# 25: Список реквизитов моих платежных методов
|
|
367
|
-
@abstractmethod
|
|
368
|
-
async def creds(self) -> list[CredExOut]: ... # {credex.exid: {cred}}
|
|
369
|
-
|
|
370
494
|
# Создание реквизита на бирже
|
|
371
495
|
async def cred_new(self, cred: models.Cred) -> models.CredEx: ...
|
|
372
496
|
|
|
@@ -387,16 +511,16 @@ class BaseAgentClient(HttpClient, BaseInAgentClient):
|
|
|
387
511
|
# # # Ad
|
|
388
512
|
# 29: Список моих объявлений
|
|
389
513
|
@abstractmethod
|
|
390
|
-
async def
|
|
514
|
+
async def get_my_ads(self, status: bool = None) -> list[BaseAd | BaseCredexsExidsTrait]: ...
|
|
391
515
|
|
|
392
516
|
@abstractmethod
|
|
393
|
-
async def x2e_req_ad_upd(self, xreq:
|
|
517
|
+
async def x2e_req_ad_upd(self, xreq: AdUpdReq) -> BaseAd: ...
|
|
394
518
|
|
|
395
519
|
# 30: Создание объявления
|
|
396
520
|
@abstractmethod
|
|
397
521
|
async def ad_new(self, ad: BaseAd) -> Ad: ...
|
|
398
522
|
|
|
399
|
-
async def ad_upd(self, xreq:
|
|
523
|
+
async def ad_upd(self, xreq: AdUpdReq) -> Ad:
|
|
400
524
|
xreq.credexs = await models.CredEx.filter(
|
|
401
525
|
ex_id=self.actor.ex_id,
|
|
402
526
|
cred__pmcur__pm_id__in=xreq.pm_ids,
|
|
@@ -409,7 +533,7 @@ class BaseAgentClient(HttpClient, BaseInAgentClient):
|
|
|
409
533
|
|
|
410
534
|
# 31: Редактирование объявления
|
|
411
535
|
@abstractmethod
|
|
412
|
-
async def _ad_upd(self, ad:
|
|
536
|
+
async def _ad_upd(self, ad: BaseAd) -> Ad: ...
|
|
413
537
|
|
|
414
538
|
# 32: Удаление
|
|
415
539
|
@abstractmethod
|