xync-client 0.0.162__py3-none-any.whl → 0.0.172__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 -22
- xync_client/Abc/Ex.py +107 -127
- xync_client/Abc/Order.py +16 -17
- xync_client/Abc/xtype.py +139 -65
- xync_client/BingX/agent.py +1 -1
- xync_client/BitGet/agent.py +1 -3
- xync_client/Bybit/agent.py +80 -331
- xync_client/Bybit/etype/ad.py +79 -58
- xync_client/Bybit/etype/cred.py +25 -3
- xync_client/Bybit/etype/order.py +150 -95
- xync_client/Bybit/ex.py +24 -12
- xync_client/Bybit/{InAgent.py → inAgent.py} +5 -10
- xync_client/Bybit/order.py +33 -16
- xync_client/Htx/agent.py +9 -9
- xync_client/Htx/etype/ad.py +2 -4
- xync_client/Htx/etype/test.py +4 -4
- xync_client/Htx/ex.py +35 -3
- xync_client/Mexc/agent.py +6 -6
- xync_client/Mexc/ex.py +2 -2
- xync_client/TgWallet/agent.py +21 -21
- xync_client/TgWallet/ex.py +11 -11
- xync_client/TgWallet/pyd.py +5 -5
- xync_client/pm_unifier.py +3 -2
- {xync_client-0.0.162.dist-info → xync_client-0.0.172.dist-info}/METADATA +1 -1
- {xync_client-0.0.162.dist-info → xync_client-0.0.172.dist-info}/RECORD +27 -27
- {xync_client-0.0.162.dist-info → xync_client-0.0.172.dist-info}/WHEEL +0 -0
- {xync_client-0.0.162.dist-info → xync_client-0.0.172.dist-info}/top_level.txt +0 -0
xync_client/Bybit/agent.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import json
|
|
3
3
|
import logging
|
|
4
|
-
import re
|
|
5
4
|
from asyncio import sleep, gather
|
|
6
5
|
from asyncio.tasks import create_task
|
|
7
6
|
from datetime import datetime, timedelta, timezone
|
|
@@ -9,7 +8,6 @@ from difflib import SequenceMatcher
|
|
|
9
8
|
from enum import IntEnum
|
|
10
9
|
from hashlib import sha256
|
|
11
10
|
from http.client import HTTPException
|
|
12
|
-
from math import floor
|
|
13
11
|
from typing import Literal
|
|
14
12
|
from uuid import uuid4
|
|
15
13
|
|
|
@@ -21,27 +19,24 @@ from bybit_p2p._exceptions import FailedRequestError
|
|
|
21
19
|
from payeer_api import PayeerAPI
|
|
22
20
|
from pyro_client.client.file import FileClient
|
|
23
21
|
from tortoise import BaseDBAsyncClient
|
|
24
|
-
from tortoise.exceptions import IntegrityError
|
|
25
|
-
from tortoise.expressions import Q
|
|
26
|
-
from tortoise.functions import Count
|
|
27
22
|
from tortoise.signals import post_save
|
|
28
23
|
from tortoise.timezone import now
|
|
29
24
|
from tortoise.transactions import in_transaction
|
|
25
|
+
from websockets import ConnectionClosedError
|
|
30
26
|
from x_client import df_hdrs
|
|
31
27
|
from x_model import init_db
|
|
32
|
-
from x_model.func import ArrayAgg
|
|
33
28
|
from xync_bot import XyncBot
|
|
34
29
|
|
|
35
30
|
from xync_client.Bybit.ex import ExClient
|
|
36
31
|
from xync_schema import models
|
|
37
32
|
from xync_schema.enums import OrderStatus, AgentStatus
|
|
38
33
|
|
|
39
|
-
from xync_schema.models import
|
|
34
|
+
from xync_schema.models import Agent
|
|
40
35
|
|
|
41
36
|
from xync_client.Abc.Agent import BaseAgentClient
|
|
42
|
-
from xync_client.Abc.xtype import FlatDict, BaseOrderReq,
|
|
43
|
-
from xync_client.Bybit.etype.ad import AdPostRequest,
|
|
44
|
-
from xync_client.Bybit.etype.cred import CredEpyd
|
|
37
|
+
from xync_client.Abc.xtype import FlatDict, BaseOrderReq, AdUpdReq, GetAdsReq
|
|
38
|
+
from xync_client.Bybit.etype.ad import AdPostRequest, AdRequest, Ad, AdStatusReq, MyAd
|
|
39
|
+
from xync_client.Bybit.etype.cred import CredEpyd, PaymentTerm, CredEx
|
|
45
40
|
from xync_client.Bybit.etype.order import (
|
|
46
41
|
OrderRequest,
|
|
47
42
|
PreOrderResp,
|
|
@@ -77,6 +72,7 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
77
72
|
# rewrite token for public methods
|
|
78
73
|
api: P2P
|
|
79
74
|
orders: dict[int, tuple[models.Order, OrderFull]] = {} # pending
|
|
75
|
+
cdx_cls: type[CredEx] = CredEx
|
|
80
76
|
|
|
81
77
|
def __init__(
|
|
82
78
|
self,
|
|
@@ -122,95 +118,11 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
122
118
|
def get_payment_method(self, fiat_id: int) -> CredEpyd:
|
|
123
119
|
return self.creds()[fiat_id]
|
|
124
120
|
|
|
125
|
-
def
|
|
121
|
+
async def _get_creds(self) -> list[PaymentTerm]:
|
|
126
122
|
data = self.api.get_user_payment_types()
|
|
127
123
|
if data["ret_code"] > 0:
|
|
128
124
|
return data
|
|
129
|
-
return
|
|
130
|
-
|
|
131
|
-
async def cred_epyd2db(self, ecdx: CredEpyd, pers_id: int = None, cur_id: int = None) -> models.CredEx | None:
|
|
132
|
-
if ecdx.paymentType in (416,): # what is 416??
|
|
133
|
-
return None
|
|
134
|
-
if not (
|
|
135
|
-
pmex := await models.PmEx.get_or_none(exid=ecdx.paymentType, ex=self.ex_client.ex).prefetch_related(
|
|
136
|
-
"pm__curs"
|
|
137
|
-
)
|
|
138
|
-
):
|
|
139
|
-
raise HTTPException(f"No PmEx {ecdx.paymentType} on ex#{self.ex_client.ex.name}", 404)
|
|
140
|
-
if cred_old := await models.Cred.get_or_none(credexs__exid=ecdx.id, credexs__ex=self.actor.ex).prefetch_related(
|
|
141
|
-
"pmcur"
|
|
142
|
-
):
|
|
143
|
-
cur_id = cred_old.pmcur.cur_id
|
|
144
|
-
elif not cur_id: # is new Cred
|
|
145
|
-
cur_id = (
|
|
146
|
-
pmex.pm.df_cur_id
|
|
147
|
-
or await self.guess_cur(ecdx, len(pmex.pm.curs) > 1 and pmex.pm.curs)
|
|
148
|
-
or (pmex.pm.country_id and (await pmex.pm.country).cur_id)
|
|
149
|
-
# or (ecdx.currencyBalance and await models.Cur.get_or_none(ticker=ecdx.currencyBalance[0])) # это че еще за хуйня?
|
|
150
|
-
)
|
|
151
|
-
if not cur_id:
|
|
152
|
-
raise Exception(f"Set default cur for {pmex.name}")
|
|
153
|
-
if not (pmcur := await models.PmCur.get_or_none(cur_id=cur_id, pm_id=pmex.pm_id)):
|
|
154
|
-
raise HTTPException(f"No PmCur with cur#{cur_id} and pm#{ecdx.paymentType}", 404)
|
|
155
|
-
xtr = ecdx.branchName
|
|
156
|
-
if ecdx.bankName:
|
|
157
|
-
xtr += (" | " if xtr else "") + ecdx.bankName
|
|
158
|
-
elif ecdx.payMessage:
|
|
159
|
-
xtr += (" | " if xtr else "") + ecdx.payMessage
|
|
160
|
-
elif ecdx.qrcode:
|
|
161
|
-
xtr += (" | " if xtr else "") + ecdx.qrcode
|
|
162
|
-
elif ecdx.paymentExt1:
|
|
163
|
-
xtr += (" | " if xtr else "") + ecdx.paymentExt1
|
|
164
|
-
try:
|
|
165
|
-
cred_db, _ = await models.Cred.update_or_create(
|
|
166
|
-
{
|
|
167
|
-
"name": ecdx.realName,
|
|
168
|
-
"extra": xtr,
|
|
169
|
-
},
|
|
170
|
-
pmcur=pmcur,
|
|
171
|
-
person_id=pers_id or self.actor.person_id,
|
|
172
|
-
detail=ecdx.accountNo or ecdx.payMessage,
|
|
173
|
-
)
|
|
174
|
-
if cred_db.ovr_pm_id is None and (cred_db.detail.startswith("XyncPay") or xtr.startswith("XyncPay")):
|
|
175
|
-
cred_db.ovr_pm_id = 0
|
|
176
|
-
await cred_db.save()
|
|
177
|
-
credex_in = models.CredEx.validate({"exid": ecdx.id, "cred_id": cred_db.id, "ex_id": self.actor.ex.id})
|
|
178
|
-
credex_db, _ = await models.CredEx.update_or_create(**credex_in.df_unq())
|
|
179
|
-
except IntegrityError as e:
|
|
180
|
-
raise e
|
|
181
|
-
return credex_db
|
|
182
|
-
|
|
183
|
-
async def guess_cur(self, ecdx: CredEpyd, curs: list[models.Cur]):
|
|
184
|
-
mbs = ecdx.bankName.split(", ")
|
|
185
|
-
mbs += ecdx.branchName.split(" / ")
|
|
186
|
-
mbs = {mb.lower(): mb for mb in mbs}
|
|
187
|
-
if (
|
|
188
|
-
pms := await models.Pm.filter(Q(join_type="OR", pmexs__name__in=mbs.values(), norm__in=mbs.keys()))
|
|
189
|
-
.group_by("pmcurs__cur_id", "pmcurs__cur__ticker")
|
|
190
|
-
.annotate(ccnt=Count("id"), names=ArrayAgg("norm"))
|
|
191
|
-
.order_by("-ccnt", "pmcurs__cur__ticker")
|
|
192
|
-
.values("pmcurs__cur_id", "names", "ccnt")
|
|
193
|
-
):
|
|
194
|
-
return pms[0]["pmcurs__cur_id"]
|
|
195
|
-
curs = {c.ticker: c.id for c in curs or await models.Cur.all()}
|
|
196
|
-
for cur, cid in curs.items():
|
|
197
|
-
if re.search(re.compile(rf"\({cur}\)$"), ecdx.bankName):
|
|
198
|
-
return cid
|
|
199
|
-
if re.search(re.compile(rf"\({cur}\)$"), ecdx.branchName):
|
|
200
|
-
return cid
|
|
201
|
-
if re.search(re.compile(rf"\({cur}\)$"), ecdx.accountNo):
|
|
202
|
-
return cid
|
|
203
|
-
if re.search(re.compile(rf"\({cur}\)$"), ecdx.payMessage):
|
|
204
|
-
return cid
|
|
205
|
-
if re.search(re.compile(rf"\({cur}\)$"), ecdx.paymentExt1):
|
|
206
|
-
return cid
|
|
207
|
-
return None
|
|
208
|
-
|
|
209
|
-
# 25: Список реквизитов моих платежных методов
|
|
210
|
-
async def set_creds(self) -> list[models.CredEx]:
|
|
211
|
-
credexs_epyd: dict[int, CredEpyd] = self.creds()
|
|
212
|
-
credexs: list[models.CredEx] = [await self.cred_epyd2db(f) for f in credexs_epyd.values()]
|
|
213
|
-
return credexs
|
|
125
|
+
return [PaymentTerm.model_validate(credex) for credex in data["result"] if credex["id"] != "-1"]
|
|
214
126
|
|
|
215
127
|
async def ott(self):
|
|
216
128
|
t = await self._post("/x-api/user/private/ott")
|
|
@@ -238,7 +150,7 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
238
150
|
delete = await self._post("/x-api/fiat/otc/user/payment/new_delete", data)
|
|
239
151
|
return delete
|
|
240
152
|
|
|
241
|
-
async def switch_ads(self, new_status:
|
|
153
|
+
async def switch_ads(self, new_status: AdStatusReq) -> dict:
|
|
242
154
|
data = {"workStatus": new_status.name} # todo: переделать на апи, там status 0 -> 1
|
|
243
155
|
res = await self._post("/x-api/fiat/otc/maker/work-config/switch", data)
|
|
244
156
|
return res
|
|
@@ -248,26 +160,16 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
248
160
|
ads = [ad for ad in list_ads if set(ad["payments"]) - {"5", "51"}]
|
|
249
161
|
return float(ads[0]["price"])
|
|
250
162
|
|
|
251
|
-
def
|
|
252
|
-
resp = self.api.get_ads_list(
|
|
163
|
+
async def get_my_ads(self, active: bool = True, page: int = 1) -> list[MyAd]:
|
|
164
|
+
resp = self.api.get_ads_list(
|
|
165
|
+
size="30", page=str(page), status=AdStatusReq.active if active else AdStatusReq.sold_out
|
|
166
|
+
)
|
|
253
167
|
ads = [MyAd.model_validate(ad) for ad in resp["result"]["items"]]
|
|
254
|
-
|
|
255
|
-
|
|
168
|
+
# todo: вернуть, что бы спарсил все объявы, а не только первые 30
|
|
169
|
+
# if resp["result"]["count"] > 30 * page:
|
|
170
|
+
# ads.extend(await self.get_my_ads(active, page + 1))
|
|
256
171
|
return ads
|
|
257
172
|
|
|
258
|
-
async def export_my_ads(self, active: bool = None) -> int: # upserted)
|
|
259
|
-
ads = self.my_ads(True)
|
|
260
|
-
if not active:
|
|
261
|
-
ads += self.my_ads(False)
|
|
262
|
-
for ad in ads:
|
|
263
|
-
ad_db = await self.ex_client.ad_load(ad, maker=self.actor)
|
|
264
|
-
mad_db, _ = await models.MyAd.update_or_create(ad=ad_db)
|
|
265
|
-
exids = [pt.id for pt in ad.paymentTerms]
|
|
266
|
-
credexs = await models.CredEx.filter(ex_id=self.actor.ex_id, exid__in=exids).prefetch_related("cred")
|
|
267
|
-
await mad_db.credexs.clear()
|
|
268
|
-
await mad_db.credexs.add(*credexs)
|
|
269
|
-
return len(ads)
|
|
270
|
-
|
|
271
173
|
async def ads_share(self, cur_id: int = None) -> int:
|
|
272
174
|
mq = models.MyAd.hot_mads_query([4]).filter(ad__maker=self.actor)
|
|
273
175
|
if cur_id:
|
|
@@ -276,9 +178,7 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
276
178
|
return len([await self.ad_share(mad.id) for mad in mads])
|
|
277
179
|
|
|
278
180
|
async def ad_share(self, maid: int):
|
|
279
|
-
myad = await models.MyAd.get(id=maid).prefetch_related(
|
|
280
|
-
"ad__pair_side__pair__coin", "ad__pair_side__pair__cur", "ad__maker"
|
|
281
|
-
)
|
|
181
|
+
myad = await models.MyAd.get(id=maid).prefetch_related("ad__pair_side__pair__coin", "ad__pair_side__pair__cur")
|
|
282
182
|
if myad.hex and myad.shared_at + timedelta(minutes=55) > now(): # check expired
|
|
283
183
|
# check validity
|
|
284
184
|
data = await self._post("/x-api/fiat/otc/item/shareItem/info", {"shareCode": myad.hex.hex()})
|
|
@@ -286,14 +186,14 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
286
186
|
return myad.get_url()
|
|
287
187
|
data = await self._post("/x-api/fiat/otc/item/share", {"itemId": str(myad.ad.exid)})
|
|
288
188
|
if data["ret_code"] == 912300058:
|
|
289
|
-
raise ShareException(
|
|
290
|
-
|
|
291
|
-
)
|
|
292
|
-
|
|
293
|
-
raise ShareException(f"Торговля агента {myad.ad.maker.agent_id} выключена")
|
|
294
|
-
if data["ret_code"] == 10007:
|
|
189
|
+
raise ShareException(f"Ad {myad.id}:{myad.ad.id}:{myad.ad.exid} agent:{myad.ad.maker.agent_id} offline")
|
|
190
|
+
elif data["ret_code"] == 912300059:
|
|
191
|
+
raise ShareException(f"Торговля мейкера {myad.ad.maker_id} выключена")
|
|
192
|
+
elif data["ret_code"] == 10007:
|
|
295
193
|
raise ShareException(f"Авторизация агента {myad.ad.maker.agent_id} слетела")
|
|
296
|
-
|
|
194
|
+
elif data["ret_code"] == 912300064:
|
|
195
|
+
raise ShareException(f"Ad {myad.ad.exid} maker:{myad.ad.maker_id} shared too much")
|
|
196
|
+
elif data["ret_code"] != 0: # Новая ошибка
|
|
297
197
|
raise ShareException(data)
|
|
298
198
|
url = data["result"]["shareLink"]
|
|
299
199
|
resp = await self.session.get(url)
|
|
@@ -375,8 +275,8 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
375
275
|
data = self.api.post_new_ad(**ad.model_dump())
|
|
376
276
|
return data["result"]["itemId"] if data["ret_code"] == 0 else data
|
|
377
277
|
|
|
378
|
-
async def _ad_upd(self, req:
|
|
379
|
-
upd =
|
|
278
|
+
async def _ad_upd(self, req: AdUpdReq):
|
|
279
|
+
upd = AdRequest({})
|
|
380
280
|
params = upd.model_dump()
|
|
381
281
|
data = self.api.update_ad(**params)
|
|
382
282
|
return data["result"] if data["ret_code"] == 0 else data
|
|
@@ -420,9 +320,9 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
420
320
|
tokenId=bor.coin_exid,
|
|
421
321
|
currencyId=bor.cur_exid,
|
|
422
322
|
side="1" if bor.is_sell else "0",
|
|
423
|
-
amount=f"{bor.
|
|
323
|
+
amount=f"{bor.amount:.2f}".rstrip("0").rstrip("."),
|
|
424
324
|
curPrice=por.curPrice,
|
|
425
|
-
quantity=str(round(bor.
|
|
325
|
+
quantity=str(round(bor.amount / float(por.price), bor.coin_scale)),
|
|
426
326
|
flag="amount",
|
|
427
327
|
# online="0"
|
|
428
328
|
)
|
|
@@ -533,155 +433,6 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
533
433
|
},
|
|
534
434
|
)
|
|
535
435
|
|
|
536
|
-
async def create_order_db(self, order: OrderFull) -> models.Order:
|
|
537
|
-
curex = await models.CurEx.get_or_none(ex=self.ex_client.ex, exid=order.currencyId).prefetch_related("cur")
|
|
538
|
-
cur_scale = (curex.scale if curex.scale is not None else curex.cur.scale) if curex else 2
|
|
539
|
-
coinex = await models.CoinEx.get(ex=self.ex_client.ex, exid=order.tokenId).prefetch_related("coin")
|
|
540
|
-
coin_scale = coinex.scale if coinex.scale is not None else coinex.cur.scale
|
|
541
|
-
sb_names = order.sellerRealName, order.buyerRealName
|
|
542
|
-
im_maker = int(int(order.makerUserId) == self.actor.exid)
|
|
543
|
-
taker_id = (order.userId, order.targetUserId)[im_maker]
|
|
544
|
-
taker_name = sb_names[order.side] # todo: double check
|
|
545
|
-
taker_person = await self.ex_client.person_name_update(taker_name, taker_id)
|
|
546
|
-
seller_person = (
|
|
547
|
-
self.actor.person
|
|
548
|
-
if order.side
|
|
549
|
-
else await self.ex_client.person_name_update(order.sellerRealName, int(order.targetUserId))
|
|
550
|
-
)
|
|
551
|
-
taker_nick = (self.actor.name, order.targetNickName)[im_maker] # todo: check
|
|
552
|
-
ad_db = await models.Ad.get(exid=order.itemId)
|
|
553
|
-
if not ad_db:
|
|
554
|
-
ad = self.get_ad(order.itemId)
|
|
555
|
-
# ad_db, cond_isnew = await self.ex_client.cond_load(ad, force=True, rname=maker_name[order.side])
|
|
556
|
-
ad_db = await self.ex_client.ad_load(ad, maker=self.actor)
|
|
557
|
-
ecredex: CredEpyd = order.confirmedPayTerm
|
|
558
|
-
|
|
559
|
-
if ecredex.paymentType == 0 and im_maker and order.side:
|
|
560
|
-
ecredex = order.paymentTermList[0]
|
|
561
|
-
if ecredex.paymentType:
|
|
562
|
-
if ecredex.paymentType == 51:
|
|
563
|
-
ecredex.accountNo = ecredex.accountNo.replace("p", "P").replace("р", "P").replace("Р", "P")
|
|
564
|
-
# if not re.match(r"^([Pp])\d{7,10}$", ecredex.accountNo):
|
|
565
|
-
# msgs = self.api.get_chat_messages(orderId=order.id, size=100)["result"]["result"]
|
|
566
|
-
# msgs = [m["message"] for m in msgs if m["roleType"] == "user" and m["userId"] == order.targetUserId]
|
|
567
|
-
# msgs = [g.group() for m in msgs if (g := re.match(r"([PpРр])\d{7,10}\b", m))]
|
|
568
|
-
# crd = await models.Cred.get_or_none(
|
|
569
|
-
# detail=ecredex.accountNo, credexs__exid=ecredex.id, credexs__ex=self.ex_client.ex
|
|
570
|
-
# )
|
|
571
|
-
# if not msgs and re.match(r"^\d{7,10}$", ecredex.accountNo):
|
|
572
|
-
# ecredex.accountNo = "P" + ecredex.accountNo
|
|
573
|
-
# elif msgs:
|
|
574
|
-
# ecredex.accountNo = msgs[-1]
|
|
575
|
-
# else:
|
|
576
|
-
# ...
|
|
577
|
-
# if crd:
|
|
578
|
-
# crd.detail = ecredex.accountNo
|
|
579
|
-
# await crd.save(update_fields=["detail"])
|
|
580
|
-
if not (credex := await models.CredEx.get_or_none(exid=ecredex.id, ex=self.ex_client.ex)):
|
|
581
|
-
# cur_id = await Cur.get(ticker=ad.currencyId).values_list('id', flat=True)
|
|
582
|
-
# await self.cred_epyd2db(ecredex, ad_db.maker.person_id, cur_id)
|
|
583
|
-
if (
|
|
584
|
-
await PmCur.filter(
|
|
585
|
-
pm__pmexs__ex=self.ex_client.ex,
|
|
586
|
-
pm__pmexs__exid=ecredex.paymentType,
|
|
587
|
-
cur__ticker=order.currencyId,
|
|
588
|
-
).count()
|
|
589
|
-
!= 1
|
|
590
|
-
):
|
|
591
|
-
...
|
|
592
|
-
if not (
|
|
593
|
-
pmcur := await PmCur.get_or_none(
|
|
594
|
-
pm__pmexs__ex=self.ex_client.ex,
|
|
595
|
-
pm__pmexs__exid=ecredex.paymentType,
|
|
596
|
-
cur__ticker=order.currencyId,
|
|
597
|
-
)
|
|
598
|
-
):
|
|
599
|
-
...
|
|
600
|
-
if not (
|
|
601
|
-
crd := await models.Cred.get_or_none(pmcur=pmcur, person=seller_person, detail=ecredex.accountNo)
|
|
602
|
-
):
|
|
603
|
-
extr = ", ".join(
|
|
604
|
-
x
|
|
605
|
-
for xtr in [
|
|
606
|
-
ecredex.bankName,
|
|
607
|
-
ecredex.branchName,
|
|
608
|
-
ecredex.qrcode,
|
|
609
|
-
ecredex.payMessage,
|
|
610
|
-
ecredex.paymentExt1,
|
|
611
|
-
]
|
|
612
|
-
if (x := xtr.strip())
|
|
613
|
-
)
|
|
614
|
-
crd = await models.Cred.create(
|
|
615
|
-
detail=ecredex.accountNo,
|
|
616
|
-
pmcur=pmcur,
|
|
617
|
-
person=seller_person,
|
|
618
|
-
name=ecredex.realName,
|
|
619
|
-
extra=extr,
|
|
620
|
-
)
|
|
621
|
-
credex = await models.CredEx.create(exid=ecredex.id, ex=self.ex_client.ex, cred=crd)
|
|
622
|
-
try:
|
|
623
|
-
taker, _ = await Actor.get_or_create(
|
|
624
|
-
{"name": taker_nick, "person": taker_person}, ex=self.ex_client.ex, exid=taker_id
|
|
625
|
-
)
|
|
626
|
-
except IntegrityError as e:
|
|
627
|
-
logging.error(e)
|
|
628
|
-
odb, _ = await models.Order.update_or_create(
|
|
629
|
-
{
|
|
630
|
-
"amount": float(order.amount) * 10**cur_scale,
|
|
631
|
-
"quantity": float(order.quantity) * 10**coin_scale,
|
|
632
|
-
"status": OrderStatus[Status(order.status).name],
|
|
633
|
-
"created_at": ms2utc(order.createDate),
|
|
634
|
-
"payed_at": order.transferDate != "0" and ms2utc(order.transferDate) or None,
|
|
635
|
-
"confirmed_at": Status(order.status) == Status.completed and ms2utc(order.transferDate) or None,
|
|
636
|
-
"appealed_at": order.status == 30 and ms2utc(order.transferDate) or None,
|
|
637
|
-
"cred_id": ecredex.paymentType and credex.cred_id or None,
|
|
638
|
-
"taker": taker,
|
|
639
|
-
"ad": ad_db,
|
|
640
|
-
},
|
|
641
|
-
exid=order.id,
|
|
642
|
-
)
|
|
643
|
-
if order.status == Status.completed and ecredex.paymentType == 51:
|
|
644
|
-
await odb.fetch_related("cred", "transfer")
|
|
645
|
-
if odb.cred.detail != ecredex.accountNo:
|
|
646
|
-
...
|
|
647
|
-
frm = (odb.created_at + timedelta(minutes=180 - 1)).isoformat(sep=" ").split("+")[0]
|
|
648
|
-
to = ((odb.payed_at or odb.created_at) + timedelta(minutes=180 + 30)).isoformat(sep=" ").split("+")[0]
|
|
649
|
-
tsa = [
|
|
650
|
-
t
|
|
651
|
-
for tid, t in (self.hist.items() if self.hist else [])
|
|
652
|
-
if (ecredex.accountNo == t["to"] and t["from"] != "@merchant" and frm < t["date"] < to)
|
|
653
|
-
]
|
|
654
|
-
buyer_person = (
|
|
655
|
-
self.actor.person
|
|
656
|
-
if not order.side
|
|
657
|
-
else await self.ex_client.person_name_update(order.buyerRealName, int(order.targetUserId))
|
|
658
|
-
)
|
|
659
|
-
ts = [t for t in tsa if floor(fa := float(order.amount)) <= float(t["creditedAmount"]) <= round(fa)]
|
|
660
|
-
if len(ts) != 1:
|
|
661
|
-
if len(tsa) > 1:
|
|
662
|
-
summ = sum(float(t["creditedAmount"]) for t in tsa)
|
|
663
|
-
if floor(fa) <= summ <= round(fa):
|
|
664
|
-
for tr in tsa:
|
|
665
|
-
am = int(float(tr["creditedAmount"]) * 100)
|
|
666
|
-
await models.Transfer.create(
|
|
667
|
-
pmid=tr["id"], order=odb, amount=am, sender_acc=tr["from"], created_at=tr["date"]
|
|
668
|
-
)
|
|
669
|
-
else:
|
|
670
|
-
bcred, _ = await models.Cred.get_or_create(
|
|
671
|
-
{"detail": ts[0]["from"]}, person=buyer_person, pmcur_id=odb.cred.pmcur_id
|
|
672
|
-
)
|
|
673
|
-
am = int(float(ts[0]["creditedAmount"]) * 100)
|
|
674
|
-
try:
|
|
675
|
-
await models.Transfer.create(
|
|
676
|
-
pmid=ts[0]["id"], order=odb, amount=am, sender_acc=ts[0]["from"], created_at=ts[0]["date"]
|
|
677
|
-
)
|
|
678
|
-
except IntegrityError as e:
|
|
679
|
-
logging.error(e)
|
|
680
|
-
...
|
|
681
|
-
|
|
682
|
-
await odb.fetch_related("ad")
|
|
683
|
-
return odb
|
|
684
|
-
|
|
685
436
|
async def get_api_orders(
|
|
686
437
|
self,
|
|
687
438
|
page: int = 1,
|
|
@@ -710,7 +461,7 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
710
461
|
if o.status != Status.completed.value or oid in self.completed_orders:
|
|
711
462
|
continue
|
|
712
463
|
order = await self.get_order_full(o.id)
|
|
713
|
-
order_db = await self.
|
|
464
|
+
order_db = await self.order_save(order)
|
|
714
465
|
await sleep(1)
|
|
715
466
|
dmsgs = self.api.get_chat_messages(orderId=oid, size=200)["result"]["result"][::-1]
|
|
716
467
|
msgs = [Message.model_validate(m) for m in dmsgs if m["msgType"] in (1, 2, 7, 8)]
|
|
@@ -773,7 +524,7 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
773
524
|
|
|
774
525
|
bor = BaseOrderReq(
|
|
775
526
|
ad_id=str(req.ad_id),
|
|
776
|
-
|
|
527
|
+
amount=req.amount,
|
|
777
528
|
is_sell=req.is_sell,
|
|
778
529
|
cur_exid=curex.exid,
|
|
779
530
|
coin_exid=coinex.exid,
|
|
@@ -790,7 +541,7 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
790
541
|
i = 0
|
|
791
542
|
while True:
|
|
792
543
|
try:
|
|
793
|
-
breq =
|
|
544
|
+
breq = GetAdsReq(coin_id=1, cur_id=1, is_sell=False, limit=50)
|
|
794
545
|
bs = await self.ex_client.ads(breq, post_pmexs=post_pmexs)
|
|
795
546
|
bs = [b for b in bs if float(b.price) < 100 or int(b.userId) in mcs.keys()]
|
|
796
547
|
if bs:
|
|
@@ -812,7 +563,7 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
812
563
|
ord_resp: OrderResp = await self.take_ad(req)
|
|
813
564
|
# order: OrderFull = OrderFull(**self.api.get_order_details(orderId=ord_resp.orderId)["result"])
|
|
814
565
|
order: OrderFull = await self.get_order_info(ord_resp.orderId)
|
|
815
|
-
odb = await self.
|
|
566
|
+
odb = await self.order_save(order)
|
|
816
567
|
t = await models.Transfer(order=odb, amount=odb.amount, updated_at=now())
|
|
817
568
|
await t.fetch_related("order__cred__pmcur__cur")
|
|
818
569
|
# res = await self.pm_clients[366].send(t)
|
|
@@ -828,7 +579,7 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
828
579
|
|
|
829
580
|
await sleep(5)
|
|
830
581
|
|
|
831
|
-
sreq =
|
|
582
|
+
sreq = GetAdsReq(coin_id=1, cur_id=1, is_sell=True, limit=50, kwargs={"post_pmexs": post_pmexs})
|
|
832
583
|
ss = await self.ex_client.ads(sreq, post_pmexs=post_pmexs)
|
|
833
584
|
ss = [s for s in ss if float(s.price) > 92 or int(s.userId) in mcs.keys()]
|
|
834
585
|
if ss:
|
|
@@ -850,7 +601,7 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
850
601
|
ord_resp: OrderResp = await self.take_ad(req)
|
|
851
602
|
# order: OrderFull = OrderFull(**self.api.get_order_details(orderId=ord_resp.orderId)["result"])
|
|
852
603
|
order: OrderFull = await self.get_order_info(ord_resp.orderId)
|
|
853
|
-
odb = await self.
|
|
604
|
+
odb = await self.order_save(order)
|
|
854
605
|
# t = await models.Transfer(order=odb, amount=odb.amount, updated_at=now())
|
|
855
606
|
# await t.fetch_related("order__cred__pmcur__cur")
|
|
856
607
|
# res = await self.pm_clients[366].check_in(t)
|
|
@@ -881,7 +632,7 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
881
632
|
req = TakeAdReq(ad_id="1856989782009487360", amount=am, pm_id=366)
|
|
882
633
|
ord_resp: OrderResp = await self.take_ad(req)
|
|
883
634
|
order: OrderFull = await self.get_order_full(int(ord_resp.orderId))
|
|
884
|
-
odb = await self.
|
|
635
|
+
odb = await self.order_save(order)
|
|
885
636
|
t = await models.Transfer(order=odb, amount=odb.amount, updated_at=now())
|
|
886
637
|
await t.fetch_related("order__cred__pmcur__cur")
|
|
887
638
|
await self.pm_clients[366].send(t)
|
|
@@ -928,10 +679,14 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
928
679
|
|
|
929
680
|
sub_msg = json.dumps({"op": "subscribe", "args": ["FIAT_OTC_TOPIC", "FIAT_OTC_ONLINE_TOPIC"]})
|
|
930
681
|
await websocket.send(sub_msg)
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
682
|
+
try:
|
|
683
|
+
while resp := await websocket.recv():
|
|
684
|
+
if data := json.loads(resp):
|
|
685
|
+
logging.info(f" {now().strftime('%H:%M:%S')} upd: {data.get('topic')}:{data.get('type')}")
|
|
686
|
+
await self.proc(data)
|
|
687
|
+
except ConnectionClosedError as e:
|
|
688
|
+
logging.warning(e)
|
|
689
|
+
await self._start_listen()
|
|
935
690
|
|
|
936
691
|
async def proc(self, data: dict):
|
|
937
692
|
match data.get("topic"):
|
|
@@ -939,10 +694,12 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
939
694
|
match data["type"]:
|
|
940
695
|
case "STATUS_CHANGE":
|
|
941
696
|
upd = StatusChange.model_validate(data["data"])
|
|
942
|
-
|
|
697
|
+
if not upd.status:
|
|
698
|
+
logging.warning(data["data"])
|
|
699
|
+
order_db, order = await self.load_order(upd.exid)
|
|
943
700
|
match upd.status:
|
|
944
|
-
case
|
|
945
|
-
logging.info(f"Order {upd.
|
|
701
|
+
case OrderStatus.created:
|
|
702
|
+
logging.info(f"Order {upd.exid} CREATED at {upd.created_at}")
|
|
946
703
|
# await self.got_new_order(order_db, order)
|
|
947
704
|
|
|
948
705
|
# # сразу уменьшаем доступный остаток монеты/валюты
|
|
@@ -953,8 +710,8 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
953
710
|
# return
|
|
954
711
|
# await order_db.fetch_related("ad__pair_side__pair", "cred__pmcur__cur")
|
|
955
712
|
# await self.send_payment(order_db)
|
|
956
|
-
|
|
957
|
-
if upd.
|
|
713
|
+
# case OrderStatus.created:
|
|
714
|
+
if upd.ad__pair_side__is_sell == 0: # я продавец, ждем когда покупатель оплатит
|
|
958
715
|
# check_payment() # again
|
|
959
716
|
...
|
|
960
717
|
# if not (pmacdx := await self.get_pma_by_cdex(order)):
|
|
@@ -992,7 +749,7 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
992
749
|
# for o in pos.get("items", [])
|
|
993
750
|
# if (
|
|
994
751
|
# o["amount"] == order.amount
|
|
995
|
-
# and o["id"] != upd.
|
|
752
|
+
# and o["id"] != upd.exid
|
|
996
753
|
# and int(order.createDate) < int(o["createDate"]) + 15 * 60 * 1000
|
|
997
754
|
# # get full_order from o, and cred or pm from full_order:
|
|
998
755
|
# and self.api.get_order_details(orderId=o["id"])["result"][
|
|
@@ -1019,53 +776,53 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
1019
776
|
# return
|
|
1020
777
|
#
|
|
1021
778
|
# # !!! ОТПРАВЛЯЕМ ДЕНЬГИ !!!
|
|
1022
|
-
# self.api.release_assets(orderId=upd.
|
|
779
|
+
# self.api.release_assets(orderId=upd.exid)
|
|
1023
780
|
# logging.info(
|
|
1024
781
|
# f"Order {order.id} created, paid before #{tid}:{am} at {order.createDate}, and RELEASED at {now()}"
|
|
1025
782
|
# )
|
|
1026
|
-
elif upd.
|
|
783
|
+
elif upd.ad__pair_side__is_sell == 1: # я покупатель - ждем мою оплату
|
|
1027
784
|
# pay()
|
|
1028
|
-
logging.warning(f"Order {upd.
|
|
785
|
+
logging.warning(f"Order {upd.exid} CREATED2 at {now()}")
|
|
1029
786
|
|
|
1030
|
-
case
|
|
787
|
+
case OrderStatus.paid:
|
|
1031
788
|
if order_db.status == OrderStatus.paid:
|
|
1032
789
|
return
|
|
1033
790
|
await order_db.update_from_dict(
|
|
1034
791
|
{
|
|
1035
792
|
"status": OrderStatus.paid,
|
|
1036
|
-
"payed_at":
|
|
793
|
+
"payed_at": order.payed_at,
|
|
1037
794
|
}
|
|
1038
795
|
).save()
|
|
1039
|
-
logging.info(f"Order {order.
|
|
796
|
+
logging.info(f"Order {order.exid} payed at {order_db.payed_at}")
|
|
1040
797
|
|
|
1041
|
-
case
|
|
798
|
+
case OrderStatus.appealed_by_seller: # just any appealed
|
|
1042
799
|
# todo: appealed by WHO? щас наугад стоит by_seller
|
|
1043
800
|
await order_db.update_from_dict(
|
|
1044
801
|
{
|
|
1045
802
|
"status": OrderStatus.appealed_by_seller,
|
|
1046
|
-
"appealed_at":
|
|
803
|
+
"appealed_at": order.appealed_at,
|
|
1047
804
|
}
|
|
1048
805
|
).save()
|
|
1049
|
-
logging.info(f"Order {order.
|
|
806
|
+
logging.info(f"Order {order.exid} appealed at {order_db.appealed_at}")
|
|
1050
807
|
|
|
1051
|
-
case
|
|
808
|
+
case OrderStatus.canceled:
|
|
1052
809
|
await order_db.update_from_dict({"status": OrderStatus.canceled}).save()
|
|
1053
|
-
logging.info(f"Order {order.
|
|
810
|
+
logging.info(f"Order {order.exid} canceled at {datetime.now()}")
|
|
1054
811
|
# await self.money_upd(order_db)
|
|
1055
812
|
|
|
1056
|
-
case
|
|
813
|
+
case OrderStatus.completed:
|
|
1057
814
|
await order_db.refresh_from_db()
|
|
1058
815
|
if order_db.status != OrderStatus.completed:
|
|
1059
816
|
await order_db.update_from_dict(
|
|
1060
817
|
{
|
|
1061
818
|
"status": OrderStatus.completed,
|
|
1062
|
-
"confirmed_at":
|
|
819
|
+
"confirmed_at": order.confirmed_at,
|
|
1063
820
|
}
|
|
1064
821
|
).save(update_fields=["status", "confirmed_at"])
|
|
1065
822
|
# await self.money_upd(order_db)
|
|
1066
823
|
|
|
1067
824
|
case _:
|
|
1068
|
-
logging.warning(f"Order {order.
|
|
825
|
+
logging.warning(f"Order {order.exid} UNKNOWN STATUS {datetime.now()}")
|
|
1069
826
|
case "COUNT_DOWN":
|
|
1070
827
|
upd = CountDown.model_validate(data["data"])
|
|
1071
828
|
|
|
@@ -1082,7 +839,7 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
1082
839
|
# msg, _ = await models.Msg.update_or_create(
|
|
1083
840
|
# {
|
|
1084
841
|
# "to_maker": upd.userId == self.actor.exid and im_taker,
|
|
1085
|
-
# "sent_at":
|
|
842
|
+
# "sent_at": upd.createDate,
|
|
1086
843
|
# },
|
|
1087
844
|
# txt=upd.message,
|
|
1088
845
|
# order=order_db,
|
|
@@ -1114,29 +871,19 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
1114
871
|
# self.listen(data)
|
|
1115
872
|
case "SELLER_CANCEL_CHANGE":
|
|
1116
873
|
upd = SellerCancelChange.model_validate(data["data"])
|
|
874
|
+
order_db, order = await self.load_order(upd.id)
|
|
875
|
+
await order_db.cancel_request(self.agent.actor_id)
|
|
1117
876
|
case None:
|
|
1118
877
|
if not data.get("success"):
|
|
1119
|
-
|
|
878
|
+
raise HTTPException(401 if data["ret_msg"] == "Request not authorized" else data)
|
|
1120
879
|
else:
|
|
1121
880
|
return # success login, subscribes, input
|
|
1122
881
|
case _:
|
|
1123
882
|
logging.warning(data, "UNKNOWN TOPIC")
|
|
1124
883
|
|
|
1125
|
-
async def
|
|
1126
|
-
|
|
1127
|
-
return OrderFull.model_validate(
|
|
1128
|
-
|
|
1129
|
-
async def load_order(self, oid: int) -> tuple[models.Order, OrderFull]:
|
|
1130
|
-
if not self.orders.get(oid):
|
|
1131
|
-
order = await self.get_order_full(oid)
|
|
1132
|
-
if not (
|
|
1133
|
-
order_db := await models.Order.get_or_none(exid=oid, ad__maker__ex=self.actor.ex).prefetch_related(
|
|
1134
|
-
"ad__pair_side__pair", "cred__pmcur__cur"
|
|
1135
|
-
)
|
|
1136
|
-
):
|
|
1137
|
-
order_db = await self.create_order_db(order)
|
|
1138
|
-
self.orders[oid] = order_db, order
|
|
1139
|
-
return self.orders[oid]
|
|
884
|
+
async def _get_order_full(self, order_exid: int) -> OrderFull:
|
|
885
|
+
order_dict: dict = self.api.get_order_details(orderId=order_exid)["result"]
|
|
886
|
+
return OrderFull.model_validate(order_dict)
|
|
1140
887
|
|
|
1141
888
|
async def money_upd(self, odb: models.Order):
|
|
1142
889
|
# обновляем остаток монеты
|
|
@@ -1303,7 +1050,7 @@ async def main():
|
|
|
1303
1050
|
cn = await init_db(TORM)
|
|
1304
1051
|
|
|
1305
1052
|
agent = (
|
|
1306
|
-
await models.Agent.filter(actor__ex_id=4, auth__isnull=False, status__gt=AgentStatus.off, id=
|
|
1053
|
+
await models.Agent.filter(actor__ex_id=4, auth__isnull=False, status__gt=AgentStatus.off, id=2)
|
|
1307
1054
|
.prefetch_related(
|
|
1308
1055
|
"actor__ex",
|
|
1309
1056
|
"actor__person__user__gmail",
|
|
@@ -1317,11 +1064,11 @@ async def main():
|
|
|
1317
1064
|
# await filebot.start()
|
|
1318
1065
|
# b.add_handler(MessageHandler(cond_start_handler, command("cond")))
|
|
1319
1066
|
ex = await models.Ex.get(name="Bybit")
|
|
1320
|
-
|
|
1067
|
+
prx = PRX and "http://" + PRX
|
|
1068
|
+
ecl: ExClient = ex.client(filebot, proxy=prx)
|
|
1321
1069
|
abot = XyncBot(PAY_TOKEN, cn)
|
|
1322
1070
|
# pmas = await models.PmAgent.filter(active=True, user_id=1).prefetch_related("pm", "user__gmail")
|
|
1323
1071
|
# pm_clients = {pma.pm_id: pma.client(abot) for pma in pmas}
|
|
1324
|
-
prx = PRX and "http://" + PRX
|
|
1325
1072
|
cl: AgentClient = agent.client(ecl, filebot, abot, proxy=prx)
|
|
1326
1073
|
|
|
1327
1074
|
# req = TakeAdReq(ad_id=1955696985964089344, amount=504, pm_id=128)
|
|
@@ -1330,11 +1077,13 @@ async def main():
|
|
|
1330
1077
|
# await cl.actual_cond()
|
|
1331
1078
|
# cl.get_api_orders(), # 10, 1738357200000, 1742504399999
|
|
1332
1079
|
|
|
1080
|
+
# await cl.ex_client.set_coins()
|
|
1081
|
+
# await cl.ex_client.set_curs()
|
|
1333
1082
|
# await cl.ex_client.set_pairs()
|
|
1334
1083
|
# await cl.ex_client.set_pms()
|
|
1335
1084
|
|
|
1336
|
-
await cl.
|
|
1337
|
-
await cl.
|
|
1085
|
+
# await cl.load_creds()
|
|
1086
|
+
# await cl.load_my_ads()
|
|
1338
1087
|
|
|
1339
1088
|
my_ad = await models.MyAd[5]
|
|
1340
1089
|
await cl.ad_share(my_ad.id)
|
|
@@ -1383,7 +1132,7 @@ async def main():
|
|
|
1383
1132
|
|
|
1384
1133
|
# await cl.cancel_order(res.orderId)
|
|
1385
1134
|
await filebot.stop()
|
|
1386
|
-
await cl.
|
|
1135
|
+
await cl.stop()
|
|
1387
1136
|
|
|
1388
1137
|
|
|
1389
1138
|
if __name__ == "__main__":
|