xync-client 0.0.155__py3-none-any.whl → 0.0.162__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.
File without changes
@@ -13,9 +13,21 @@ class AdStatus(StrEnum):
13
13
 
14
14
 
15
15
  class AdsReq(BaseModel):
16
- tokenId: str
17
- currencyId: str
18
- side: Literal["0", "1"] # 0 покупка, # 1 продажа
16
+ tokenId: str = Field(validation_alias="coin_id")
17
+ currencyId: str = Field(validation_alias="cur_id")
18
+ side: Literal["0", "1"] = Field(validation_alias="is_sell") # 0 покупка, # 1 продажа
19
+ payment: list[str] = Field([], validation_alias="pm_ids") # int
20
+ size: str = Field("20", validation_alias="limit") # int
21
+ page: str = "1" # int
22
+ amount: str = "" # float
23
+ vaMaker: bool = Field(False, validation_alias="vm_only")
24
+ canTrade: bool = False
25
+ userId: str = "" # int
26
+ verificationFilter: Literal[0, 1, 2] = 0
27
+ sortType: Literal["OVERALL_RANKING", "TRADE_VOLUME", "TRADE_COMPLETION_RATE", "TRADE_PRICE"] = "OVERALL_RANKING"
28
+ paymentPeriod: Literal[[], [15], [30], [60]] = []
29
+ itemRegion: int = 1
30
+ bulkMaker: bool = False
19
31
 
20
32
 
21
33
  class Currency(BaseModel):
@@ -79,7 +91,39 @@ class TradingPreferenceSet(BaseModel):
79
91
  registerTimeThreshold: int
80
92
 
81
93
 
94
+ class AdPostRequest(BaseModel):
95
+ tokenId: str
96
+ currencyId: str
97
+ side: Literal[0, 1] # 0 - покупка, 1 - продажа
98
+ priceType: Literal[0, 1] # 0 - fix rate, 1 - floating
99
+ premium: str
100
+ price: str
101
+ minAmount: str
102
+ maxAmount: str
103
+ remark: str
104
+ tradingPreferenceSet: TradingPreferenceSet
105
+ paymentIds: list[str] # list[int]
106
+ quantity: str # float
107
+ paymentPeriod: int = 15
108
+ itemType: Literal["ORIGIN", "BULK"] = "ORIGIN"
109
+
110
+
111
+ class AdUpdateRequest(AdPostRequest, BaseAdUpdate):
112
+ actionType: Literal["MODIFY", "ACTIVE"] = "MODIFY"
113
+
114
+
82
115
  class Ad(BaseAd):
116
+ tokenId: str = None # for initial actualize
117
+ currencyId: str = None # for initial actualize
118
+ side: Literal[0, 1] = None # for initial actualize # 0 - покупка, 1 - продажа (для мейкера, т.е КАКАЯ объява)
119
+ priceType: Literal[0, 1] = None # for initial actualize # 0 - fix rate, 1 - floating
120
+ premium: str = None # for initial actualize
121
+ price: str = None # for initial actualize
122
+ maxAmount: str = Field(serialization_alias="max_fiat")
123
+ minAmount: str = Field(serialization_alias="min_fiat")
124
+ remark: str = Field(serialization_alias="auto_msg")
125
+ tradingPreferenceSet: TradingPreferenceSet | None = None # for initial actualize
126
+
83
127
  accountId: str = None # for initial actualize
84
128
  authStatus: int = None # for initial actualize
85
129
  authTag: List[str] = None # for initial actualize
@@ -87,7 +131,6 @@ class Ad(BaseAd):
87
131
  baned: bool = None # for initial actualize
88
132
  blocked: str = None # for initial actualize
89
133
  createDate: str = None # for initial actualize
90
- currencyId: str = None # for initial actualize
91
134
  executedQuantity: str = None # for initial actualize
92
135
  fee: str = None # for initial actualize
93
136
  finishNum: int = None # for initial actualize
@@ -98,27 +141,18 @@ class Ad(BaseAd):
98
141
  lastLogoutTime: str = None # for initial actualize
99
142
  lastQuantity: str = Field(serialization_alias="quantity")
100
143
  makerContact: bool = None # for initial actualize
101
- maxAmount: str = Field(serialization_alias="max_fiat")
102
- minAmount: str = Field(serialization_alias="min_fiat")
103
144
  nickName: str = None # for initial actualize
104
145
  orderNum: int = None # for initial actualize
105
146
  paymentPeriod: int = None # for initial actualize
106
147
  payments: List[str] = None # for initial actualize
107
- premium: str = None # for initial actualize
108
- price: str = None # for initial actualize
109
- priceType: Literal[0, 1] = None # for initial actualize # 0 - fix rate, 1 - floating
110
148
  quantity: str = Field(serialization_alias="allQuantity") # for initial actualize
111
149
  recentExecuteRate: int = None # for initial actualize
112
150
  recentOrderNum: int = None # for initial actualize
113
151
  recommend: bool = None # for initial actualize
114
152
  recommendTag: str = None # for initial actualize
115
- remark: str = Field(serialization_alias="auto_msg")
116
- side: Literal[0, 1] = None # for initial actualize # 0 - покупка, 1 - продажа (для мейкера, т.е КАКАЯ объява)
117
153
  status: Literal[10, 20, 30] # 10: online; 20: offline; 30: completed
118
154
  symbolInfo: SymbolInfo = None # for initial actualize
119
- tokenId: str = None # for initial actualize
120
155
  tokenName: str = None # for initial actualize
121
- tradingPreferenceSet: TradingPreferenceSet | None = None # for initial actualize
122
156
  userId: str
123
157
  userMaskId: str = None # for initial actualize
124
158
  userType: str = None # for initial actualize
@@ -134,24 +168,3 @@ class Ad(BaseAd):
134
168
 
135
169
  class MyAd(Ad):
136
170
  paymentTerms: List[MyPaymentTerm]
137
-
138
-
139
- class AdPostRequest(BaseModel):
140
- tokenId: str
141
- currencyId: str
142
- side: Literal[0, 1] # 0 - покупка, 1 - продажа
143
- priceType: Literal[0, 1] # 0 - fix rate, 1 - floating
144
- premium: str
145
- price: str
146
- minAmount: str
147
- maxAmount: str
148
- remark: str
149
- tradingPreferenceSet: TradingPreferenceSet
150
- paymentIds: list[str]
151
- quantity: str
152
- paymentPeriod: int
153
- itemType: str
154
-
155
-
156
- class AdUpdateRequest(AdPostRequest, BaseAdUpdate):
157
- actionType: Literal["MODIFY", "ACTIVE"] = "MODIFY"
@@ -1,8 +1,9 @@
1
1
  from enum import IntEnum
2
- from typing import Literal
2
+ from typing import Literal, ClassVar
3
3
 
4
4
  from pydantic import BaseModel
5
5
 
6
+ from xync_client.Abc.xtype import RemapBase
6
7
  from xync_client.Bybit.etype.cred import CredEpyd, PaymentTerm as CredPaymentTerm, PaymentConfigVo
7
8
 
8
9
 
@@ -14,34 +15,20 @@ class Topic(IntEnum):
14
15
 
15
16
 
16
17
  class Status(IntEnum):
17
- deleted = 40 # order canceled
18
- created = 10
19
- appealable = 20 # waiting for seller to release
20
- canceled = 40
18
+ ws_new = 1
19
+ # chain = 5 # waiting for chain (only web3)
20
+ created = 10 # waiting for buyer to pay
21
+ paid = 20 # waiting for seller to release
22
+ appealed_by_seller = 30 # appealing
23
+ # appealed_by_buyer = 30 # the same appealing
24
+ canceled = 40 # order cancelled
21
25
  completed = 50 # order finished
22
- appealed_by_buyer = 30 # appealing
23
- appealed_by_seller = 30
24
- buyer_appeal_disputed_by_seller = 30
25
- paid = 50
26
- rejected = 40
27
- request_canceled = 40
28
- seller_appeal_disputed_by_buyer = 30
29
-
30
-
31
- class StatusApi(IntEnum):
32
- created = 1
33
- _web3 = 5
34
- wait_for_buyer = 10 # ws_canceled
35
- wait_for_seller = 20
36
- appealed = 30
37
- canceled = 40
38
- completed = 50
39
- _paying_online = 60
40
- _pay_fail_online = 70
41
- hotswap_cancelled = 80
42
- _buyer_sel_tokenId = 90
43
- objectioning = 100
44
- waiting_for_objection = 110
26
+ # a = 60 # paying (only when paying online)
27
+ # a = 70 # pay fail (only when paying online)
28
+ # a = 80 # exception cancelled (the coin convert to other coin only hotswap)
29
+ # a = 90 # waiting for buyer to select tokenId
30
+ appeal_disputed = 100 # objectioning
31
+ appeal_dispute_disputed = 110 # waiting for the user to raise an objection
45
32
 
46
33
 
47
34
  class TakeAdReq(BaseModel):
@@ -149,9 +136,23 @@ class PaymentTerm(CredPaymentTerm):
149
136
  ruPaymentPrompt: bool
150
137
 
151
138
 
152
- class OrderItem(BaseModel):
153
- id: str
139
+ class _BaseOrder(RemapBase):
140
+ _remap: ClassVar[dict[str, dict]] = {"status": {}}
141
+
142
+ id: int
143
+ userId: int
144
+ createDate: int
154
145
  side: Literal[0, 1] # int: 0 покупка, 1 продажа (именно для меня - апи агента, и пох мейкер я или тейкер)
146
+ status: Literal[*[s.value for s in Status]]
147
+
148
+
149
+ class _BaseChange(_BaseOrder):
150
+ makerUserId: int
151
+ appealedTimes: int
152
+ totalAppealedTimes: int
153
+
154
+
155
+ class OrderItem(_BaseOrder):
155
156
  tokenId: str
156
157
  orderType: Literal[
157
158
  "ORIGIN", "SMALL_COIN", "WEB3"
@@ -164,14 +165,9 @@ class OrderItem(BaseModel):
164
165
  fee: str
165
166
  targetNickName: str
166
167
  targetUserId: str # не я
167
- status: Literal[
168
- 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110
169
- ] # 5: waiting for chain (only web3), 10: waiting for buyer to pay, 20: waiting for seller to release, 30: appealing, 40: order cancelled, 50: order finished, 60: paying (only when paying online), 70: pay fail (only when paying online), 80: exception cancelled (the coin convert to other coin, only hotswap), 90: waiting for buyer to select tokenId, 100: objectioning, 110: waiting for the user to raise an objection
170
168
  selfUnreadMsgCount: str
171
- createDate: str
172
169
  transferLastSeconds: str
173
170
  appealLastSeconds: str
174
- userId: str # я
175
171
  sellerRealName: str
176
172
  buyerRealName: str
177
173
  judgeInfo: JudgeInfo
@@ -181,7 +177,7 @@ class OrderItem(BaseModel):
181
177
 
182
178
 
183
179
  class OrderFull(OrderItem):
184
- itemId: str
180
+ itemId: int
185
181
  makerUserId: str
186
182
  targetAccountId: str
187
183
  targetFirstName: str
@@ -284,17 +280,6 @@ class Message(BaseModel):
284
280
  onlyForCustomer: int | None = None
285
281
 
286
282
 
287
- class _BaseChange(BaseModel):
288
- userId: int
289
- makerUserId: int
290
- id: str
291
- createDate: int
292
- side: int
293
- appealedTimes: int
294
- totalAppealedTimes: int
295
- status: StatusApi | None = None
296
-
297
-
298
283
  class StatusChange(_BaseChange):
299
284
  appealVersion: int = None
300
285
 
@@ -305,7 +290,7 @@ class CountDown(_BaseChange):
305
290
 
306
291
  class _BaseMsg(BaseModel):
307
292
  userId: int
308
- orderId: str
293
+ orderId: int
309
294
  message: str = None
310
295
  msgUuid: str
311
296
  msgUuId: str
@@ -323,7 +308,7 @@ class Receive(_BaseMsg):
323
308
  class Read(_BaseMsg):
324
309
  readAmount: int
325
310
  read: Literal["101", "110", "11", "111"]
326
- orderStatus: StatusApi
311
+ orderStatus: Status
327
312
 
328
313
 
329
314
  class SellerCancelChange(BaseModel):
xync_client/Bybit/ex.py CHANGED
@@ -11,7 +11,7 @@ from xync_schema.models import Ex, Agent
11
11
  from xync_client.Abc.Ex import BaseExClient
12
12
  from xync_client.loader import NET_TOKEN
13
13
  from xync_client.Bybit.etype import ad
14
- from xync_client.Abc.xtype import PmEx, MapOfIdsList
14
+ from xync_client.Abc.xtype import PmEx, MapOfIdsList, GetAds
15
15
  from xync_client.loader import TORM
16
16
 
17
17
 
@@ -81,47 +81,20 @@ class ExClient(BaseExClient): # Bybit client
81
81
  return cc, cc
82
82
 
83
83
  # 24: Список объяв по (buy/sell, cur, coin, pm)
84
- async def ads(
85
- self,
86
- coin_exid: str,
87
- cur_exid: str,
88
- is_sell: bool,
89
- pm_exids: list[str | int] = None,
90
- amount: int = None,
91
- lim: int = 50,
92
- vm_filter: bool = False,
93
- ) -> list[ad.Ad]:
94
- data = {
95
- "userId": "",
96
- "tokenId": coin_exid,
97
- "currencyId": cur_exid,
98
- "payment": pm_exids or [],
99
- "side": "0" if is_sell else "1",
100
- "size": str(lim) if lim else "20",
101
- "page": "1",
102
- "amount": str(amount) if amount else "",
103
- "vaMaker": vm_filter,
104
- "bulkMaker": False,
105
- "canTrade": False,
106
- "verificationFilter": 0,
107
- "sortType": "OVERALL_RANKING",
108
- "paymentPeriod": [],
109
- "itemRegion": 1,
110
- }
111
- # {
112
- # "userId": "",
113
- # "tokenId": coin_exid,
114
- # "currencyId": cur_exid,
115
- # "payment": pm_exids or [],
116
- # "side": "0" if is_sell else "1",
117
- # "size": lim and str(lim) or "200",
118
- # "page": "1",
119
- # "amount": str(amount) if amount else "",
120
- # "authMaker": False,
121
- # "canTrade": False,
122
- # }
123
- ads = await self._post("/fiat/otc/item/online/", data)
124
- return [ad.Ad(**_ad) for _ad in ads["result"]["items"]]
84
+ async def _ads(self, req: ad.AdsReq, post_pmexs: set[models.PmEx] = None) -> list[ad.Ad]:
85
+ if post_pmexs:
86
+ req.payment = []
87
+ req.size = str(min(1000, int(req.size) * 25))
88
+ res = await self._post("/fiat/otc/item/online/", req.model_dump())
89
+ ads = [ad.Ad(**_ad) for _ad in res["result"]["items"]]
90
+ if post_pmexs:
91
+ post_pmexids = {p.exid for p in post_pmexs}
92
+ ads = [
93
+ ad
94
+ for ad in ads
95
+ if (set(ad.payments) & post_pmexids or [True for px in post_pmexs if px.pm.norm in ad.remark.lower()])
96
+ ]
97
+ return ads
125
98
 
126
99
 
127
100
  async def main():
@@ -130,10 +103,11 @@ async def main():
130
103
  bot: FileClient = FileClient(NET_TOKEN)
131
104
  # await bot.start()
132
105
  cl = ExClient(ex, bot)
133
- await cl.set_pms()
134
- await cl.set_coins()
135
- await cl.set_pairs()
136
- _ads = await cl.ads("USDT", "GEL", False)
106
+ # await cl.set_pms()
107
+ # await cl.set_coins()
108
+ # await cl.set_pairs()
109
+ x_ads_req = GetAds(coin_id=1, cur_id=1, is_sell=True, pm_ids=[330, 366, 1853], amount=1000)
110
+ _ads = await cl.ads(x_ads_req)
137
111
  # await bot.stop()
138
112
  await cl.close()
139
113
 
@@ -1,26 +1,28 @@
1
- from xync_schema.models import Order
1
+ from xync_client.Bybit.etype.cred import PaymentTerm
2
+ from xync_schema.models import CredEx, PmEx
2
3
 
3
4
  from xync_client.Abc.Order import BaseOrderClient
4
5
 
5
6
 
6
7
  class OrderClient(BaseOrderClient):
7
- # 2: Отмена своего запроса на сделку
8
- async def cancel_request(self) -> Order: ...
9
-
10
- # 3: Одобрить запрос на сделку
11
- async def accept_request(self) -> bool: ...
12
-
13
- # 4: Отклонить чужой запрос на сделку
14
- async def reject_request(self) -> bool: ...
15
-
16
8
  # 5: Перевод сделки в состояние "оплачено", c отправкой чека
17
- async def mark_payed(self, receipt): ...
9
+ async def mark_payed(self, payterm: PaymentTerm = None, receipt: bytes = None):
10
+ if payterm:
11
+ pt = str(payterm.paymentType)
12
+ pid = payterm.id
13
+ else:
14
+ pmx = await PmEx.get(pm__pmcurs__id=self.order.cred.pmcur_id, ex=self.agent_client.ex_client.ex)
15
+ pt = pmx.exid
16
+ cdx = await CredEx.get(cred_id=self.order.cred_id, ex=self.agent_client.ex_client.ex)
17
+ pid = str(cdx.exid)
18
+ self.agent_client.api.mark_as_paid(orderId=str(self.order.exid), paymentType=pt, paymentId=pid)
18
19
 
19
20
  # 6: Отмена одобренной сделки
20
21
  async def cancel_order(self) -> bool: ...
21
22
 
22
23
  # 7: Подтвердить получение оплаты
23
- async def confirm(self) -> bool: ...
24
+ async def confirm(self):
25
+ self.agent_client.api.release_assets(orderId=str(self.order.exid))
24
26
 
25
27
  # 9, 10: Подать аппеляцию cо скриншотом/видео/файлом
26
28
  async def start_appeal(self, file) -> bool: ...
xync_client/Htx/agent.py CHANGED
@@ -10,11 +10,10 @@ from x_client.aiohttp import Client
10
10
  from xync_bot import XyncBot
11
11
 
12
12
  from xync_client.Abc.xtype import AdUpd, GetAds
13
+ from xync_client.Htx.etype.order import OrderItem, OrderFull
13
14
  from xync_client.loader import NET_TOKEN, PAY_TOKEN, TORM
14
15
 
15
- from xync_client.Htx.etype.ad import Req, TradeRule, TradeRulesV2
16
16
  from xync_schema.enums import AdStatus, PmType, OrderStatus
17
- from xync_schema.models import Pm, Coin, Cur, Ad, Order
18
17
  from xync_schema import models
19
18
  from xync_client.Abc.Agent import BaseAgentClient
20
19
  from xync_client.Htx.etype import test, ad
@@ -39,6 +38,8 @@ class AgentClient(BaseAgentClient):
39
38
  async def login(self):
40
39
  t = int(time() * 1000)
41
40
  resp = await self._get("/-/x/uc/uc/open/ticket/get", {"t": t})
41
+ if resp.get("data") is None:
42
+ ...
42
43
  if ticket := resp["data"].get("ticket"):
43
44
  resp = await self._post("/-/x/otc/v1/user/login", form_data={"ticket": ticket, "type": "WEB"})
44
45
  if resp["success"]:
@@ -115,14 +116,40 @@ class AgentClient(BaseAgentClient):
115
116
 
116
117
  # 0
117
118
  async def get_orders(
118
- self, stauts: OrderStatus = OrderStatus.created, coin: Coin = None, cur: Cur = None, is_sell: bool = None
119
- ) -> list[Order]:
120
- pass
119
+ self,
120
+ stauts: OrderStatus = OrderStatus.created,
121
+ coin: models.Coin = None,
122
+ cur: models.Cur = None,
123
+ is_sell: bool = None,
124
+ ) -> list[OrderItem]:
125
+ resp = await self._get("/-/x/otc/v1/trade/order/process", {"needTradeCount": "true"})
126
+ if resp["success"]:
127
+ return [OrderItem(**o) for o in resp["data"]]
128
+ return []
129
+
130
+ async def get_order(self, oid: int) -> OrderFull | None:
131
+ resp = await self._get("/-/x/otc/v1/trade/order", {"orderId": oid})
132
+ if resp["success"]:
133
+ o = OrderFull(**resp["data"])
134
+ return o
135
+ return None
136
+
137
+ async def recv(self, order: OrderItem):
138
+ if order.orderStatus:
139
+ ...
140
+ else:
141
+ ...
142
+
143
+ async def start_listen(self):
144
+ """Фоновая задача для ловли входящих ордеров"""
145
+ while True:
146
+ [await self.recv(o) for o in await self.get_orders()]
147
+ await sleep(9)
121
148
 
122
149
  async def order_request(self, ad_id: int, amount: float) -> dict:
123
150
  pass
124
151
 
125
- async def my_fiats(self, cur: Cur = None) -> list[dict]:
152
+ async def my_fiats(self, cur: models.Cur = None) -> list[dict]:
126
153
  pass
127
154
 
128
155
  # async def fiat_new(self, fiat: FiatNew) -> Fiat.pyd():
@@ -144,22 +171,22 @@ class AgentClient(BaseAgentClient):
144
171
 
145
172
  async def ad_new(
146
173
  self,
147
- coin: Coin,
148
- cur: Cur,
174
+ coin: models.Coin,
175
+ cur: models.Cur,
149
176
  is_sell: bool,
150
- pms: list[Pm],
177
+ pms: list[models.Pm],
151
178
  price: float,
152
179
  is_float: bool = True,
153
180
  min_fiat: int = None,
154
181
  details: str = None,
155
182
  autoreply: str = None,
156
183
  status: AdStatus = AdStatus.active,
157
- ) -> Ad:
184
+ ) -> models.Ad:
158
185
  pass
159
186
 
160
- async def _ad_upd(self, ad_upd: AdUpd, hdrs: dict[str, str] = None) -> dict:
187
+ async def x2e_req_ad_upd(self, xreq: AdUpd) -> ad.AdsUpd:
161
188
  creds = [
162
- TradeRule(
189
+ ad.TradeRule(
163
190
  content="Payment method-%s",
164
191
  contentCode="PAY",
165
192
  hint="Please enter",
@@ -167,16 +194,14 @@ class AgentClient(BaseAgentClient):
167
194
  inputValue=cx.cred.detail,
168
195
  sort=1,
169
196
  title="【Payment related】",
170
- titleValue=await models.PmEx.get(pm_id=cx.cred.pmcur.pm_id, ex=self.ex_client.ex).values_list(
171
- "name", flat=True
172
- ),
197
+ titleValue=(await models.PmEx.get(pm_id=cx.cred.pmcur.pm_id, ex=self.ex_client.ex)).name,
173
198
  )
174
- for cx in ad_upd.credexs
199
+ for cx in xreq.credexs
175
200
  ]
176
- trs = TradeRulesV2(
201
+ trade_rules = ad.TradeRulesV2(
177
202
  [
178
203
  *creds,
179
- TradeRule(
204
+ ad.TradeRule(
180
205
  content="",
181
206
  contentCode="MERCHANT",
182
207
  hint="Please enter",
@@ -187,22 +212,25 @@ class AgentClient(BaseAgentClient):
187
212
  ),
188
213
  ]
189
214
  ).model_dump_json(exclude_none=True)
190
- req = Req(
191
- tradeType=int(ad_upd.is_sell),
192
- coinId=2,
193
- currency=11,
194
- minTradeLimit=500.00,
195
- maxTradeLimit=ad_upd.amount,
196
- tradeCount=ad_upd.quantity,
215
+ coin_id, coin_scale = await self.ex_client.x2e_coin(xreq.coin_id)
216
+ cur_id, cur_scale, minimum = await self.ex_client.x2e_cur(xreq.cur_id)
217
+ return ad.AdsUpd(
218
+ id=xreq.id,
219
+ tradeType=int(xreq.is_sell),
220
+ coinId=int(coin_id),
221
+ currency=int(cur_id),
222
+ minTradeLimit=minimum,
223
+ maxTradeLimit=round(xreq.amount - 10**-cur_scale, cur_scale),
224
+ tradeCount=round(xreq.quantity or xreq.amount / xreq.price, coin_scale),
197
225
  password=self.agent.auth["pass"],
198
226
  payTerm=15,
199
227
  premium=0.00,
200
228
  isFixed="on",
201
- fixedPrice=ad_upd.price,
229
+ fixedPrice=round(xreq.price, cur_scale),
202
230
  isAutoReply="off",
203
231
  takerAcceptOrder=0,
204
232
  isPayCode="off",
205
- receiveAccounts=ad_upd.credexs[0].exid,
233
+ receiveAccounts=",".join([str(cx.exid) for cx in xreq.credexs]),
206
234
  deviation=0,
207
235
  isTakerLimit="on",
208
236
  takerIsMerchant="on",
@@ -214,19 +242,20 @@ class AgentClient(BaseAgentClient):
214
242
  chargeType=False,
215
243
  apiVersion=4,
216
244
  channel="web",
217
- tradeRulesV2=quote(trs),
245
+ tradeRulesV2=quote(trade_rules),
218
246
  )
219
- res = await self._post(self.url_my_ad + str(ad_upd.id), form_data=req.model_dump(exclude_none=True), hdrs=hdrs)
247
+
248
+ async def _ad_upd(self, req: ad.AdsUpd, hdrs: dict[str, str] = None) -> dict:
249
+ res = await self._post(self.url_my_ad + str(req.id), form_data=req.model_dump(exclude_none=True), hdrs=hdrs)
220
250
  if res["code"] == 200:
221
251
  return res["data"]
222
252
  elif res["code"] == 605:
223
253
  hdrs = {"x-dialog-trace-id": res["extend"]["traceId"]}
224
- return await self._ad_upd(ad_upd, hdrs)
254
+ return await self._ad_upd(req, hdrs)
225
255
  elif res["code"] == 1010:
226
256
  if (match := re.search(r"Available amount ([\d.]+)", res["message"])) and (qty := match.group(1)):
227
- ad_upd.quantity = float(qty)
228
- ad_upd.amount = round(ad_upd.quantity * ad_upd.price, 2)
229
- return await self._ad_upd(ad_upd, hdrs)
257
+ req.tradeCount = float(qty)
258
+ return await self._ad_upd(req, hdrs)
230
259
  elif res["code"] == 401:
231
260
  raise Exception(res)
232
261
  raise BaseException(res)
@@ -304,36 +333,49 @@ async def _test():
304
333
  while True:
305
334
  breq = GetAds(coin_id=1, cur_id=1, is_sell=False, pm_ids=[366])
306
335
  sreq = GetAds(coin_id=1, cur_id=1, is_sell=True, pm_ids=[366])
307
- breq_upd = AdUpd(id=1185713, price=87.01, **{**breq.model_dump(), "amount": 80001})
308
- sreq_upd = AdUpd(id=1188929, price=92.99, **{**sreq.model_dump(), "amount": 65001})
336
+ breq_upd = AdUpd(id=1185713, price=87.01, **{**breq.model_dump(), "amount": 100000.01})
337
+ sreq_upd = AdUpd(id=1188929, price=98.99, **{**sreq.model_dump(), "amount": 200000.01})
309
338
 
310
339
  bads: list[ad.Resp] = await cl.ex_client.ads(breq)
311
340
  sads: list[ad.Resp] = await cl.ex_client.ads(sreq)
341
+ bceil = 101.11
342
+ sceil = 151
343
+ bads = [a for a in bads if a.price < bceil and a.tradeCount > 10 and (a.maxTradeLimit - a.minTradeLimit > 800)]
344
+ sads = [a for a in sads if a.price > sceil and a.tradeCount > 10 and (a.maxTradeLimit - a.minTradeLimit > 800)]
312
345
 
313
- if bads:
346
+ if len(bads) > 1:
314
347
  if bads[0].uid == cl.actor.exid:
315
348
  if round(bads[0].price - bads[1].price, 2) > 0.01:
316
349
  breq_upd.price = bads[1].price + 0.01
317
350
  await cl.ad_upd(breq_upd)
318
351
  print(end="!", flush=True)
319
- elif bads[0].price < 89:
352
+ elif bads[0].price < bceil:
320
353
  breq_upd.price = bads[0].price + 0.01
321
354
  await cl.ad_upd(breq_upd)
322
355
  print(end="!", flush=True)
323
356
 
324
- if sads:
357
+ if len(sads) > 1:
325
358
  if sads[0].uid == cl.actor.exid:
326
359
  if round(sads[1].price - sads[0].price, 2) > 0.01:
327
360
  sreq_upd.price = sads[1].price - 0.01
328
361
  await cl.ad_upd(sreq_upd)
329
362
  print(end="!", flush=True)
330
- elif sads[0].price > 91:
363
+ elif sads[0].price > sceil:
331
364
  sreq_upd.price = sads[0].price - 0.01
332
365
  await cl.ad_upd(sreq_upd)
333
366
  print(end="!", flush=True)
334
367
 
368
+ if (pos := await cl.get_orders()) and (po := pos.pop(0)):
369
+ if po.side: # is_sell
370
+ po.amount # check
371
+ else: # buy
372
+ order: OrderFull = await cl.get_order(po.orderId)
373
+ if ps := [pm.bankNumber for pm in order.paymentMethod if pm.bankType in [24]]:
374
+ if match := re.search(r"^[PpРр]\d{7,10}\b", ps[0]):
375
+ match.group()
376
+
335
377
  print(end=".", flush=True)
336
- await sleep(15)
378
+ await sleep(9)
337
379
 
338
380
  await cl.stop()
339
381