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/xtype.py CHANGED
@@ -1,9 +1,14 @@
1
+ import re
1
2
  from typing import Literal, ClassVar
2
3
 
3
- from pydantic import BaseModel, model_validator, model_serializer
4
+ from pydantic import BaseModel, model_validator, model_serializer, Field
5
+ from pydantic_core.core_schema import SerializationInfo
6
+ from tortoise.expressions import Q
7
+ from tortoise.functions import Count
8
+ from x_model.func import ArrayAgg
4
9
  from x_model.types import BaseUpd
5
- from xync_schema.enums import PmType
6
- from xync_schema.models import Country, Pm, Ex, CredEx
10
+ from xync_schema.enums import PmType, Side, AdStatus, OrderStatus
11
+ from xync_schema.models import Country, Pm, Ex, CredEx, Cur
7
12
  from xync_schema.xtype import PmExBank
8
13
 
9
14
  from xync_client.pm_unifier import PmUni
@@ -27,12 +32,13 @@ class RemapBase(BaseModel):
27
32
  return data
28
33
 
29
34
  @model_serializer
30
- def _map_out(self):
31
- data = self.__dict__.copy()
32
- for field, mapping in self._remap.items():
33
- reverse = {v: k for k, v in mapping.items()}
34
- if field in data:
35
- data[field] = reverse.get(data[field], data[field])
35
+ def _map_out(self, srlz_info: SerializationInfo):
36
+ data = dict(self)
37
+ if srlz_info.by_alias:
38
+ for field, mapping in self._remap.items():
39
+ reverse = {v: k for k, v in mapping.items()}
40
+ if field in data:
41
+ data[field] = reverse.get(data[field], data[field])
36
42
  return data
37
43
 
38
44
 
@@ -65,74 +71,80 @@ class PmExIn(BaseModel):
65
71
  arbitrary_types_allowed = True
66
72
 
67
73
 
68
- class CredExOut(BaseModel):
69
- id: int
70
-
71
-
72
- class BaseOrderReq(BaseModel):
73
- ad_id: int | str
74
-
75
- asset_amount: float | None = None
76
- fiat_amount: float | None = None
77
-
78
- pmex_exid: str = None # int
79
-
80
- # todo: mv from base to special ex class
81
- amount_is_fiat: bool = True
82
- is_sell: bool = None
83
- cur_exid: int | str = None
84
- coin_exid: int | str = None
85
- coin_scale: int = None
74
+ class BaseActor(BaseModel):
75
+ exid: int | str
76
+ nick: str | None = None
86
77
 
87
- @model_validator(mode="after")
88
- def check_a_or_b(self):
89
- if self.amount_is_fiat and not self.fiat_amount:
90
- raise ValueError("fiat_amount is required if amount_is_fiat")
91
- if not self.amount_is_fiat and not self.asset_amount:
92
- raise ValueError("asset_amount is required if not amount_is_fiat")
93
- if not self.asset_amount and not self.fiat_amount:
94
- raise ValueError("either fiat_amount or asset_amount is required")
95
- return self
96
78
 
79
+ class BaseCounteragent(BaseActor):
80
+ name: str
97
81
 
98
- class BaseOrderPaidReq(BaseModel):
99
- ad_id: int | str
100
82
 
101
- cred_id: int | None = None
102
- pm_id: int | None = None # or pmcur_id?
83
+ class BaseCredEx(BaseModel):
84
+ detail: str
85
+ exid: int | str = Field(alias="id")
86
+ extra: str | None = None
87
+ name: str
88
+ pmex_exid: int | str
89
+ curex_exid: int | str = None # fills on outer BaseOrderFull validation hook
90
+ seller: BaseCounteragent = None # fills on outer BaseOrderFull validation hook
91
+
92
+ async def guess_cur(self, curs: list[Cur] = None):
93
+ curs = {c.ticker: c.id for c in curs or await Cur.all()}
94
+ for cur, cid in curs.items():
95
+ if re.search(re.compile(rf"\({cur}\)"), self.extra + self.detail):
96
+ return cid
97
+ lower_extras = [mb.lower() for mb in self.extra.split(" | ")]
98
+ if (
99
+ pms := await Pm.filter(Q(join_type="OR", pmexs__name__in=lower_extras, norm__in=self.extra.split(" | ")))
100
+ .group_by("pmcurs__cur_id", "pmcurs__cur__ticker")
101
+ .annotate(ccnt=Count("id"), names=ArrayAgg("norm"))
102
+ .order_by("-ccnt", "pmcurs__cur__ticker")
103
+ .values("pmcurs__cur_id", "names", "ccnt")
104
+ ):
105
+ return pms[0]["pmcurs__cur_id"]
106
+ return None
107
+
108
+
109
+ class BaseAd(BaseModel):
110
+ amount: float | None = None
111
+ auto_msg: str | None = None
112
+ cond_txt: str
113
+ created_at: int # utc(0) seconds
114
+ coinex_exid: int | str
115
+ curex_exid: int | str
116
+ exid: int | str = Field(alias="id")
117
+ maker_exid: int | str
118
+ maker_name: str
119
+ maker: BaseActor = None
120
+ max_fiat: int
121
+ min_fiat: int
122
+ # paymentPeriod: int
123
+ pmex_exids: list[int | str]
124
+ premium: float
125
+ price: float
126
+ quantity: float | None = None
127
+ # recentOrderNum: int
128
+ side: Literal[Side.BUY, Side.SALE]
129
+ status: Literal[AdStatus.active, AdStatus.defActive, AdStatus.soldOut] # 10: online; 20: offline; 30: completed
103
130
 
104
131
  @model_validator(mode="after")
105
- def check_a_or_b(self):
106
- if not self.cred_id and not self.pm_id:
107
- raise ValueError("either cred_id or pm_id is required")
132
+ def amount_or_quantity_required(self):
133
+ if not self.amount and not self.quantity:
134
+ raise ValueError("either amount or quantity is required")
135
+ self.maker = BaseActor(exid=self.maker_exid, nick=self.maker_name and self.maker_name)
108
136
  return self
109
137
 
110
138
 
111
- class BaseAdUpdate(BaseModel):
112
- id: int | str
139
+ class BaseCredexsExidsTrait:
140
+ credex_exids: list[int]
113
141
 
114
142
 
115
- class BaseCad(BaseAdUpdate):
116
- id: str
117
- createDate: str
118
- currencyId: str
119
- maxAmount: str
120
- minAmount: str
121
- nickName: str
122
- paymentPeriod: int
123
- payments: list[str]
124
- premium: str
125
- price: str
126
- priceType: Literal[0, 1] # 0 - fix rate, 1 - floating
127
- quantity: str
128
- recentOrderNum: int
129
- remark: str
130
- side: Literal[0, 1] # 0 - покупка, 1 - продажа
131
- tokenId: str
132
- userId: str
143
+ class BaseCredexsTrait:
144
+ credex_exids: list[BaseCredEx]
133
145
 
134
146
 
135
- class GetAds(BaseModel):
147
+ class GetAdsReq(BaseModel):
136
148
  coin_id: int | str
137
149
  cur_id: int | str
138
150
  is_sell: bool
@@ -148,7 +160,7 @@ class GetAds(BaseModel):
148
160
  kwargs: dict = {}
149
161
 
150
162
 
151
- class AdUpd(BaseAdUpdate, GetAds):
163
+ class AdUpdReq(BaseAd, GetAdsReq):
152
164
  price: float
153
165
  pm_ids: list[int | str]
154
166
  amount: float
@@ -160,3 +172,65 @@ class AdUpd(BaseAdUpdate, GetAds):
160
172
 
161
173
  class Config:
162
174
  arbitrary_types_allowed = True
175
+
176
+
177
+ class BaseOrder(BaseModel):
178
+ ad__pair_side__is_sell: bool # int: 0 покупка, 1 продажа (именно для меня - апи агента, и пох мейкер я или тейкер)
179
+ created_at: int
180
+ exid: int = Field(alias="id")
181
+ my_exid: int | None = None # апи агент юзер
182
+ status: OrderStatus
183
+
184
+
185
+ class BaseOrderItem(BaseOrder):
186
+ amount: float | None = None
187
+ pmex_exid: int | str = None # int
188
+ quantity: float | None = None
189
+ ctr_exid: int | None = None # контрагент
190
+ ctr_nick: str | None = None
191
+ taker_exid: int | None = None # в байбите нету
192
+ curex_exid: int | str = None
193
+ coinex_exid: int | str = None
194
+ seller_name: str
195
+ buyer_name: str
196
+
197
+ @model_validator(mode="after")
198
+ def amount_or_quantity_required(self):
199
+ if not self.amount and not self.quantity:
200
+ raise ValueError("either amount or quantity is required")
201
+ return self
202
+
203
+
204
+ class BaseOrderFull(BaseOrderItem):
205
+ ad_id: int | str
206
+ ad__maker_exid: int | None = None
207
+ credex: BaseCredEx
208
+ my_nick: str = Field(alias="nickName")
209
+ taker: BaseCounteragent = None # fills on validation hook
210
+
211
+
212
+ class BaseOrderReq(BaseModel):
213
+ ad_id: int | str
214
+
215
+ quantity: float | None = None
216
+ amount: float | None = None
217
+
218
+ pmex_exid: str = None # int
219
+
220
+ is_sell: bool = None
221
+ cur_exid: int | str = None
222
+ coin_exid: int | str = None
223
+ coin_scale: int = None
224
+
225
+
226
+ class BaseOrderPaidReq(BaseModel):
227
+ ad_id: int | str
228
+
229
+ cred_id: int | None = None
230
+ pm_id: int | None = None # or pmcur_id?
231
+
232
+ @model_validator(mode="after")
233
+ def check_a_or_b(self):
234
+ if not self.cred_id and not self.pm_id:
235
+ raise ValueError("either cred_id or pm_id is required")
236
+ return self
xync_client/Binance/ex.py CHANGED
@@ -140,8 +140,8 @@ async def main():
140
140
  _ = await init_db(TORM)
141
141
  ex = await Ex.get(name="Binance")
142
142
  async with FileClient(NET_TOKEN) as b:
143
- cl = ExClient(ex, b)
144
- await cl.set_pms()
143
+ cl = ExClient(ex)
144
+ await cl.set_pms(b)
145
145
  await cl.set_coins()
146
146
  await cl.set_pairs()
147
147
  # await cl.pairs()
@@ -90,7 +90,7 @@ class AgentClient(BaseAgentClient):
90
90
  pass
91
91
 
92
92
  # 29: Список моих объявлений
93
- async def my_ads(self):
93
+ async def get_my_ads(self):
94
94
  pass
95
95
 
96
96
  # 30: Создание объявления
xync_client/BingX/ex.py CHANGED
@@ -95,7 +95,7 @@ async def main():
95
95
  bg = await Ex.get(name="BingX").prefetch_related("pm_reps")
96
96
  async with FileClient(NET_TOKEN) as b:
97
97
  b: FileClient
98
- cl = ExClient(bg, b)
98
+ cl = ExClient(bg)
99
99
  _ads = await cl.ads(
100
100
  "USDT",
101
101
  "RUB",
@@ -103,7 +103,7 @@ async def main():
103
103
  )
104
104
  await cl.set_pairs()
105
105
  await cl.set_coins()
106
- await cl.set_pms()
106
+ await cl.set_pms(b)
107
107
  # _curs = await cl.curs()
108
108
  # _coins = await cl.coins()
109
109
  # _pairs = await cl.pairs()
@@ -2,13 +2,11 @@ import json
2
2
  import subprocess
3
3
  from asyncio import run
4
4
  from x_model import init_db
5
- from xync_schema import models
6
5
  from xync_schema.enums import AdStatus, PmType, OrderStatus
7
6
  from xync_schema.models import User, Pm, Coin, Cur, Ad, Fiat, Order, Agent
8
7
  from xync_schema.pydantic import FiatNew
9
8
 
10
9
  from xync_client.Abc.Agent import BaseAgentClient
11
- from xync_client.loader import PG_DSN
12
10
 
13
11
 
14
12
  class Client(BaseAgentClient):
@@ -50,7 +48,7 @@ class Client(BaseAgentClient):
50
48
  async def fiat_del(self, fiat_id: int) -> bool:
51
49
  pass
52
50
 
53
- async def my_ads(self) -> list[Ad]:
51
+ async def get_my_ads(self) -> list[Ad]:
54
52
  pass
55
53
 
56
54
  async def ad_new(
xync_client/BitGet/ex.py CHANGED
@@ -94,15 +94,16 @@ class ExClient(BaseExClient):
94
94
  async def main():
95
95
  _ = await init_db(TORM, True)
96
96
  bg = await Ex.get(name="BitGet")
97
- cl = ExClient(bg, FileClient(NET_TOKEN))
98
- _ads = await cl.ads("USDT", "RUB", False, [])
99
- await cl.curs()
100
- await cl.coins()
101
- await cl.pms()
102
- await cl.cur_pms_map()
103
- await cl.set_pms()
104
- await cl.set_coins()
105
- await cl.close()
97
+ async with FileClient(NET_TOKEN) as b:
98
+ cl = ExClient(bg)
99
+ _ads = await cl.ads("USDT", "RUB", False, [])
100
+ await cl.curs()
101
+ await cl.coins()
102
+ await cl.pms()
103
+ await cl.cur_pms_map()
104
+ await cl.set_pms(b)
105
+ await cl.set_coins()
106
+ await cl.close()
106
107
 
107
108
 
108
109
  if __name__ == "__main__":
xync_client/BitPapa/ex.py CHANGED
@@ -20,19 +20,22 @@ class ExClient(BaseExClient):
20
20
 
21
21
 
22
22
  async def main():
23
+ from pyro_client.client.file import FileClient
23
24
  from xync_schema import TORM
25
+ from xync_client.loader import NET_TOKEN
24
26
 
25
27
  _ = await init_db(TORM, True)
26
28
  ex = await Ex.get(name="BitPapa")
27
- cl = ExClient(ex)
28
- _ads = await cl.ads(2, 11, True)
29
- await cl.set_pms()
30
- await cl.set_coins()
31
- _cr = await cl.curs()
32
- _cn = await cl.coins()
33
- await cl.set_pairs()
34
- _pms = await cl.pms()
35
- await cl.close()
29
+ async with FileClient(NET_TOKEN) as b:
30
+ cl = ExClient(ex)
31
+ _ads = await cl.ads(2, 11, True)
32
+ await cl.set_pms(b)
33
+ await cl.set_coins()
34
+ _cr = await cl.curs()
35
+ _cn = await cl.coins()
36
+ await cl.set_pairs()
37
+ _pms = await cl.pms()
38
+ await cl.close()
36
39
 
37
40
 
38
41
  if __name__ == "__main__":