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 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 pyro_client.client.file import FileClient
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, AdStatus, Actor, Agent
19
- from xync_schema.xtype import BaseAd
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 CredExOut, BaseOrderReq, BaseAdUpdate, AdUpd, GetAds
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, BaseModel]] = {} # pending
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, 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
- self.cred_x2e[cred_id] = (await models.CredEx.get(cred_id=cred_id)).exid
63
- self.cred_e2x[self.cred_x2e[cred_id]] = cred_id
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, exid: int) -> int: # cred.id
67
- if not self.cred_e2x.get(exid):
68
- self.cred_e2x[exid] = (await models.CredEx.get(exid=exid, ex=self.ex_client.ex)).cred_id
69
- self.cred_x2e[self.cred_e2x[exid]] = exid
70
- return self.cred_e2x[exid]
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 = GetAds(
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 my_ads(self, status: AdStatus = None) -> list[BaseAd]: ...
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: AdUpd) -> BaseAdUpdate: ...
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: AdUpd) -> Ad:
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: BaseAdUpdate) -> Ad: ...
536
+ async def _ad_upd(self, ad: BaseAd) -> Ad: ...
413
537
 
414
538
  # 32: Удаление
415
539
  @abstractmethod