xync-client 0.0.235__tar.gz → 0.0.236.dev1__tar.gz
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-0.0.235 → xync_client-0.0.236.dev1}/PKG-INFO +1 -1
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Abc/Agent.py +73 -24
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Abc/Ex.py +25 -11
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Abc/xtype.py +6 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Bybit/agent.py +45 -45
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Bybit/etype/ad.py +11 -3
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Bybit/ex.py +64 -2
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/details.py +4 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client.egg-info/PKG-INFO +1 -1
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/.env.sample +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/.gitignore +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/.pre-commit-config.yaml +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/CLAUDE.md +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/README.md +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/__init__.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/makefile +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/pyproject.toml +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/setup.cfg +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/tests/TestAgent.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/tests/TestAsset.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/tests/TestEx.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/tests/TestOrder.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/tests/_todo_refact/Binance/test_binance.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/tests/_todo_refact/Bybit/test_bybit.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/tests/_todo_refact/Bybit/test_bybit_p2p.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/tests/_todo_refact/Gate/test_gate.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/tests/_todo_refact/Wallet/test_agent.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/tests/_todo_refact/Wallet/test_ex.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/tests/_todo_refact/__init__.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/tests/_todo_refact/_test_ex.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Abc/AdLoader.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Abc/Asset.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Abc/Auth.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Abc/BaseTest.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Abc/Exception.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Abc/HasAbotUid.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Abc/InAgent.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Abc/Order.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Abc/PmAgent.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Binance/__init__.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Binance/binance_async.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Binance/earn_api.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Binance/etype/ad.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Binance/etype/pm.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Binance/ex.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Binance/exceptions.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Binance/sapi.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Binance/web_c2c.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/BingX/__init__.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/BingX/agent.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/BingX/base.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/BingX/etype/ad.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/BingX/etype/pm.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/BingX/ex.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/BingX/req.mjs +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/BingX/sign.js +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/BitGet/__init__.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/BitGet/agent.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/BitGet/etype/ad.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/BitGet/ex.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/BitPapa/ex.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Bybit/etype/__init__.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Bybit/etype/cred.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Bybit/etype/order.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Bybit/etype/pm.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Bybit/inAgent.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Bybit/order.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Bybit/web_earn.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Bybit/web_p2p.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Bybit/ws.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Gate/etype/ad.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Gate/ex.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Gate/premarket.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Gmail/__init__.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Htx/agent.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Htx/earn.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Htx/etype/__init__.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Htx/etype/ad.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Htx/etype/cred.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Htx/etype/order.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Htx/etype/pm.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Htx/etype/test.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Htx/ex.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/KuCoin/etype/ad.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/KuCoin/etype/pm.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/KuCoin/ex.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/KuCoin/web.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Mexc/agent.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Mexc/api.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Mexc/etype/ad.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Mexc/etype/order.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Mexc/etype/pm.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Mexc/ex.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Okx/1.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Okx/agent.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Okx/etype/ad.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Okx/etype/pm.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Okx/ex.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Pms/.gitignore +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Pms/Alfa/__init__.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Pms/Alfa/state.json +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Pms/MTS/__init__.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Pms/Ozon/__init__.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Pms/Payeer/.gitignore +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Pms/Payeer/agent.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Pms/Payeer/login.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Pms/Payeer/trade.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Pms/Sber/__init__.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Pms/Sber/utils.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Pms/Tinkoff/__init__.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Pms/Volet/_todo_req/req.mjs +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Pms/Volet/_todo_req/req.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Pms/Volet/agent.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Pms/Volet/api.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Pms/Volet/pl.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Pms/Xync/__main__.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Pms/Xync/ed.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Pms/Yandex/__init__.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/Pms/airtm/__init__.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/TgWallet/agent.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/TgWallet/asset.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/TgWallet/auth.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/TgWallet/ex.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/TgWallet/inAgent.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/TgWallet/order.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/TgWallet/pyd.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/TgWallet/pyro.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/TgWallet/web.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/__init__.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/loader.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client/pm_unifier.py +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client.egg-info/SOURCES.txt +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client.egg-info/dependency_links.txt +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client.egg-info/requires.txt +0 -0
- {xync_client-0.0.235 → xync_client-0.0.236.dev1}/xync_client.egg-info/top_level.txt +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
import math
|
|
2
3
|
from abc import abstractmethod
|
|
3
4
|
from asyncio import create_task, sleep
|
|
4
5
|
from collections import defaultdict
|
|
@@ -8,7 +9,7 @@ from pydantic import BaseModel
|
|
|
8
9
|
from tortoise.exceptions import IntegrityError
|
|
9
10
|
from x_client import df_hdrs
|
|
10
11
|
from x_client.aiohttp import Client as HttpClient
|
|
11
|
-
from xync_client.details import hot_ad_cond
|
|
12
|
+
from xync_client.details import hot_ad_cond, more1perc
|
|
12
13
|
from xync_schema.enums import AdStatus, OrderStatus
|
|
13
14
|
|
|
14
15
|
from xync_client.Abc.PmAgent import PmAgentClient
|
|
@@ -60,7 +61,7 @@ class BaseAgentClient(HttpClient, BaseInAgentClient): # , metaclass=ABCMeta
|
|
|
60
61
|
self.pm_clients: dict[int, PmAgentClient] = defaultdict()
|
|
61
62
|
super().__init__(self.actor.ex.host_p2p, headers, cookies, proxy) # and proxy.str()
|
|
62
63
|
# start
|
|
63
|
-
create_task(self.start())
|
|
64
|
+
# create_task(self.start())
|
|
64
65
|
|
|
65
66
|
async def x2e_cred(self, cred_id: int) -> int: # cred.exid
|
|
66
67
|
if not self.cred_x2e.get(cred_id):
|
|
@@ -113,7 +114,7 @@ class BaseAgentClient(HttpClient, BaseInAgentClient): # , metaclass=ABCMeta
|
|
|
113
114
|
await self.load_pending_orders()
|
|
114
115
|
await self.ads_share()
|
|
115
116
|
|
|
116
|
-
async def load_assets(self, coin_ids: list[int] = None)
|
|
117
|
+
async def load_assets(self, coin_ids: list[int] = None):
|
|
117
118
|
assets = {cid: await self.get_asset(cid) for cid in coin_ids} if coin_ids else await self.my_assets()
|
|
118
119
|
for cid, amount in assets.items():
|
|
119
120
|
await self.asset_save(cid, amount)
|
|
@@ -523,27 +524,62 @@ class BaseAgentClient(HttpClient, BaseInAgentClient): # , metaclass=ABCMeta
|
|
|
523
524
|
@abstractmethod
|
|
524
525
|
async def _ad_upd_api(self, ad: MyAdXOut) -> int: ...
|
|
525
526
|
|
|
526
|
-
|
|
527
|
+
@staticmethod
|
|
528
|
+
def fee(min_count):
|
|
529
|
+
return 7.5 * math.exp(-0.1 * min_count) + 1.1
|
|
530
|
+
|
|
531
|
+
async def ad_fresh(self, ads: list[models.Ad], is_sell: bool, bal: float, cur_min, rate: float, haq: dict) -> dict:
|
|
532
|
+
if not ads:
|
|
533
|
+
return haq
|
|
534
|
+
|
|
527
535
|
ad = await ads.pop(0).to_float(ex_id=self.actor.ex_id)
|
|
528
|
-
if ad.min_fiat
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
536
|
+
if (min_count := int(ad.min_fiat / cur_min)) in {1, 10, 60}: # is_full
|
|
537
|
+
i = (list(haq)).index((min_count, int(ad.filtered)))
|
|
538
|
+
elif 5 <= min_count < 10:
|
|
539
|
+
i = 2
|
|
540
|
+
elif 23 <= min_count < 60:
|
|
541
|
+
i = 3
|
|
542
|
+
else:
|
|
543
|
+
logging.error(f"Wrong ad.min_fiat: {ad.exid}:{ad.min_fiat}:{ad.filtered}") # need debug
|
|
544
|
+
return await self.ad_fresh(ads, is_sell, bal, cur_min, rate, haq)
|
|
545
|
+
k, fltrd = list(haq)[i]
|
|
546
|
+
target_min = cur_min * k
|
|
547
|
+
# ad.min_fiat = min(target_min, xbal)
|
|
548
|
+
|
|
549
|
+
fld = ("amount", "quantity")[
|
|
550
|
+
int(is_sell)
|
|
551
|
+
] # если покупка - отталкиваемся от имеющегося cur баланса, else - coin
|
|
552
|
+
old_bal = getattr(ad, fld)
|
|
553
|
+
setattr(ad, fld, bal)
|
|
554
|
+
setattr(ad, ("amount", "quantity")[int(not is_sell)], None) # а связанный (другой) балланс обнуляем
|
|
555
|
+
xma = MyAdXOut.model_validate(ad, from_attributes=True)
|
|
556
|
+
|
|
557
|
+
if k > 1 and xma.amount < target_min / 2: # хватает ли денег на размещение объявы
|
|
558
|
+
logging.warning(f"Less balance {bal} for {is_sell} ad:{ad.exid}:{ad.min_fiat}:{ad.filtered}")
|
|
559
|
+
return await self.ad_fresh(ads, is_sell, bal, cur_min, rate, haq)
|
|
560
|
+
|
|
561
|
+
xma.min_fiat = min(target_min, xma.amount)
|
|
562
|
+
min_count = xma.min_fiat / cur_min
|
|
563
|
+
pk = self.fee(min_count) if fltrd else 10
|
|
564
|
+
sk = 2 * int(is_sell) - 1
|
|
565
|
+
new_price = round(rate * 0.01 * (1 + sk * pk / 200), 2)
|
|
566
|
+
if xma.price != new_price or more1perc(
|
|
567
|
+
old_bal, bal
|
|
568
|
+
): # если текущий объем валюты/монеты не совпадает с текущим балансом - обновляем
|
|
569
|
+
xma.price = new_price
|
|
535
570
|
xma.cond_txt = hot_ad_cond
|
|
536
571
|
await self._ad_upd_api(xma)
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
572
|
+
haq[(k, fltrd)][int(is_sell)] += 1
|
|
573
|
+
else:
|
|
574
|
+
haq[(k, fltrd)][int(is_sell)] -= 1
|
|
575
|
+
return await self.ad_fresh(ads, is_sell, bal, cur_min, rate, haq)
|
|
540
576
|
|
|
541
|
-
async def ads_fresh(self, cur_id: int = 1, coin_id: int = 1)
|
|
577
|
+
async def ads_fresh(self, cur_id: int = 1, coin_id: int = 1):
|
|
542
578
|
"""
|
|
543
579
|
Обновляем/добавляем объявления агента, в зависимости от кол-ва объявлений которое он может размещать
|
|
544
580
|
одновременно `same_dir_ad` (от 1 до 4), и его текущего coin_balance.
|
|
545
581
|
"""
|
|
546
|
-
curex = await models.CurEx.get(cur_id=cur_id, ex_id=self.actor.ex_id)
|
|
582
|
+
curex = await models.CurEx.get(cur_id=cur_id, ex_id=self.actor.ex_id).prefetch_related("cur")
|
|
547
583
|
usdt_bal = (await self.agent.coins_balance())[coin_id]
|
|
548
584
|
xbals = await self.actor.person.user.balances()
|
|
549
585
|
xbal = xbals[cur_id]
|
|
@@ -551,10 +587,14 @@ class BaseAgentClient(HttpClient, BaseInAgentClient): # , metaclass=ABCMeta
|
|
|
551
587
|
# то постим 4 объявления:
|
|
552
588
|
# 1) с минимальным нижним лимитом размера ордера, и без фильтрации контрагентов
|
|
553
589
|
# 2) с минимальным лимитом, но с фильтрацией контрагентов
|
|
554
|
-
# 3) с 10x мин лимитом, и с фильтрацией (если вообще есть баланс от
|
|
555
|
-
# 4)
|
|
556
|
-
|
|
557
|
-
|
|
590
|
+
# 3) с 10x мин лимитом, и с фильтрацией (если вообще есть баланс хотя бы от 5x min)
|
|
591
|
+
# 4) 60x мин лимит, либо весь баланс если он меньше, с фильтрацией (если есть баланс от 30x min)
|
|
592
|
+
hot_ads_q = { # item legend: (min_multiplier, is_filtered): [buy_ad_is_posted, sell_ad_is_posted]
|
|
593
|
+
(1, 0): [0, 0],
|
|
594
|
+
(1, 1): [0, 0],
|
|
595
|
+
(10, 1): [0, 0],
|
|
596
|
+
(60, 1): [0, 0],
|
|
597
|
+
}
|
|
558
598
|
fltr = dict(
|
|
559
599
|
my_ad__credexs__cred__ovr_pm_id=0,
|
|
560
600
|
my_ad__credexs__cred__pmcur__cur_id=cur_id,
|
|
@@ -563,21 +603,30 @@ class BaseAgentClient(HttpClient, BaseInAgentClient): # , metaclass=ABCMeta
|
|
|
563
603
|
)
|
|
564
604
|
prftch = "my_ad__credexs", "pair_side__pair__coin", "pair_side__pair__cur"
|
|
565
605
|
|
|
606
|
+
if xbal < curex.minimum:
|
|
607
|
+
logging.error(f"Not enough xync balance: {xbal}")
|
|
608
|
+
return
|
|
609
|
+
|
|
566
610
|
bads = (
|
|
567
611
|
await models.Ad.filter(**fltr, status=AdStatus.active, pair_side__is_sell=False)
|
|
568
612
|
.order_by("min_fiat", "filtered")
|
|
569
613
|
.prefetch_related(*prftch)
|
|
570
614
|
.limit(self.agent.same_dir_ad)
|
|
571
615
|
)
|
|
572
|
-
await self.ad_fresh(bads, False, xbal, curex.minimum)
|
|
616
|
+
await self.ad_fresh(bads, False, xbal, curex.minimum, curex.cur.rate, hot_ads_q)
|
|
617
|
+
|
|
618
|
+
if usdt_bal * curex.cur.rate * 10**-curex.cur.scale < curex.minimum:
|
|
619
|
+
logging.error(f"Not enough {self.ex_client.ex.name} balance: {usdt_bal}")
|
|
620
|
+
return
|
|
573
621
|
|
|
574
622
|
sads = (
|
|
575
|
-
await models.Ad.filter(**fltr, status=AdStatus.active, pair_side__is_sell=
|
|
576
|
-
.order_by("min_fiat", "filtered")
|
|
623
|
+
await models.Ad.filter(**fltr, status=AdStatus.active, pair_side__is_sell=True)
|
|
624
|
+
.order_by("-min_fiat", "-filtered")
|
|
577
625
|
.prefetch_related(*prftch)
|
|
578
626
|
.limit(self.agent.same_dir_ad)
|
|
579
627
|
)
|
|
580
|
-
await self.ad_fresh(sads, True, usdt_bal, curex.minimum)
|
|
628
|
+
await self.ad_fresh(sads, True, usdt_bal, curex.minimum, curex.cur.rate, hot_ads_q)
|
|
629
|
+
return hot_ads_q
|
|
581
630
|
|
|
582
631
|
# 32: Удаление
|
|
583
632
|
@abstractmethod
|
|
@@ -4,7 +4,6 @@ from abc import abstractmethod
|
|
|
4
4
|
from asyncio import sleep
|
|
5
5
|
from collections import defaultdict
|
|
6
6
|
from difflib import SequenceMatcher
|
|
7
|
-
from math import floor
|
|
8
7
|
|
|
9
8
|
from aiohttp import ClientSession, ClientResponse
|
|
10
9
|
from msgspec import Struct
|
|
@@ -187,7 +186,6 @@ class BaseExClient(HttpClient, AdLoader):
|
|
|
187
186
|
update=dict(
|
|
188
187
|
coin_id=(await self.x2e_coin(xreq.coin_id))[0],
|
|
189
188
|
cur_id=(await self.x2e_cur(xreq.cur_id))[0],
|
|
190
|
-
is_sell=str(int(xreq.is_sell)),
|
|
191
189
|
pm_ids=xreq.pm_ids and [await self.x2e_pm(pid) for pid in xreq.pm_ids],
|
|
192
190
|
)
|
|
193
191
|
)
|
|
@@ -471,12 +469,12 @@ class BaseExClient(HttpClient, AdLoader):
|
|
|
471
469
|
badd = base_ad.model_dump()
|
|
472
470
|
pms = await models.Pm.filter(pmexs__ex=self.ex, pmexs__exid__in=base_ad.pmex_exids)
|
|
473
471
|
badd.update(
|
|
474
|
-
amount=
|
|
475
|
-
max_fiat=
|
|
476
|
-
min_fiat=
|
|
477
|
-
premium=
|
|
478
|
-
price=
|
|
479
|
-
quantity=
|
|
472
|
+
amount=round((base_ad.amount or base_ad.quantity * base_ad.price) * 10**cur_scale),
|
|
473
|
+
max_fiat=base_ad.max_fiat,
|
|
474
|
+
min_fiat=base_ad.min_fiat,
|
|
475
|
+
premium=round(base_ad.premium * 100_00),
|
|
476
|
+
price=round(base_ad.price * 10**cur_scale),
|
|
477
|
+
quantity=round((base_ad.quantity or base_ad.amount / base_ad.price) * 10**coin_scale),
|
|
480
478
|
maker_id=(await self.e2x_actor(base_ad.maker)).id,
|
|
481
479
|
cond_id=cond and cond.id,
|
|
482
480
|
pair_side_id=await self.e2x_pair(base_ad.coinex_exid, base_ad.curex_exid, bool(base_ad.side.value)),
|
|
@@ -721,9 +719,25 @@ class BaseExClient(HttpClient, AdLoader):
|
|
|
721
719
|
bc, sc = mdl + mdl * (perc / 2), mdl - mdl * (perc / 2)
|
|
722
720
|
return bc, sc
|
|
723
721
|
|
|
724
|
-
async def rate(self, cur_id: int, coin_id: int = 1) ->
|
|
725
|
-
|
|
726
|
-
|
|
722
|
+
async def rate(self, cur_id: int, coin_id: int = 1) -> float:
|
|
723
|
+
if coin_id == 1:
|
|
724
|
+
ofc = 4 if cur_id in (1, 2, 3) else 1
|
|
725
|
+
else:
|
|
726
|
+
ofc = 1 if cur_id in (1, 2, 3) else 0
|
|
727
|
+
|
|
728
|
+
bp, sp = await self.get_books(coin_id, cur_id)
|
|
729
|
+
if bp and sp:
|
|
730
|
+
return (sum(b.price for b in bp[ofc:]) / len(bp[ofc:]) + sum(s.price for s in sp[ofc:]) / len(bp[ofc:])) / 2
|
|
731
|
+
return 0
|
|
732
|
+
|
|
733
|
+
async def set_rate(self, cur_id: int, coin_id: int = 1):
|
|
734
|
+
cur = await models.Cur[cur_id]
|
|
735
|
+
rate = round(await self.rate(cur_id, coin_id), cur.scale)
|
|
736
|
+
if coin_id == 1:
|
|
737
|
+
cur.rate = rate * 10**cur.scale
|
|
738
|
+
await cur.save(update_fields=["rate"])
|
|
739
|
+
await models.Pair.filter(cur_id=cur_id, coin_id=coin_id).update(rate=rate * 10**cur.scale)
|
|
740
|
+
logging.warning(f"Set rate {coin_id}/{cur.ticker}: {rate}")
|
|
727
741
|
|
|
728
742
|
async def init_seed(self, fbot: FileClient):
|
|
729
743
|
await self.set_curs()
|
|
@@ -216,6 +216,12 @@ class MyAdXOut(AmountQuantityMixin, BaseModel):
|
|
|
216
216
|
self.maker = None
|
|
217
217
|
return self
|
|
218
218
|
|
|
219
|
+
@model_validator(mode="after")
|
|
220
|
+
def min_amount(self):
|
|
221
|
+
if self.amount < self.min_fiat:
|
|
222
|
+
self.min_fiat = int(self.amount)
|
|
223
|
+
return self
|
|
224
|
+
|
|
219
225
|
|
|
220
226
|
class BaseCredexsExidsTrait:
|
|
221
227
|
credex_exids: list[int]
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import json
|
|
3
3
|
import logging
|
|
4
|
-
from asyncio import sleep
|
|
4
|
+
from asyncio import sleep
|
|
5
5
|
from datetime import datetime, timedelta, timezone
|
|
6
6
|
from difflib import SequenceMatcher
|
|
7
7
|
from hashlib import sha256
|
|
@@ -15,7 +15,6 @@ import websockets
|
|
|
15
15
|
from aiohttp.http_exceptions import HttpProcessingError, HttpBadRequest
|
|
16
16
|
from bybit_p2p import P2P
|
|
17
17
|
from bybit_p2p._exceptions import FailedRequestError
|
|
18
|
-
from payeer_api import PayeerAPI
|
|
19
18
|
from pybit.unified_trading import HTTP
|
|
20
19
|
from tortoise import Tortoise, get_connection
|
|
21
20
|
from tortoise.timezone import now
|
|
@@ -341,6 +340,7 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
341
340
|
data = self.api.update_ad(**upd.model_dump(exclude_none=True))
|
|
342
341
|
if data["ret_code"]:
|
|
343
342
|
raise HttpBadRequest(data)
|
|
343
|
+
logging.info(f"Ad:{req.exid} upd: min:{req.min_fiat}, prc:{req.price}, qty:{req.quantity}, flt:{req.filtered}")
|
|
344
344
|
return not data["ret_code"]
|
|
345
345
|
|
|
346
346
|
def get_security_token_update(self) -> str:
|
|
@@ -1001,7 +1001,7 @@ async def main():
|
|
|
1001
1001
|
await Tortoise.init(db_url=PG_DSN, modules={"models": ["x_auth.models", "xync_schema.models"]})
|
|
1002
1002
|
|
|
1003
1003
|
agent = (
|
|
1004
|
-
await models.Agent.filter(actor__ex_id=4, auth__isnull=False, status__gt=AgentStatus.off, id=
|
|
1004
|
+
await models.Agent.filter(actor__ex_id=4, auth__isnull=False, status__gt=AgentStatus.off, id=1)
|
|
1005
1005
|
.prefetch_related(
|
|
1006
1006
|
"actor__ex",
|
|
1007
1007
|
"actor__person__user",
|
|
@@ -1033,51 +1033,51 @@ async def main():
|
|
|
1033
1033
|
# await bot.start()
|
|
1034
1034
|
# await cl.ex_client.set_pms(bot)
|
|
1035
1035
|
# await bot.stop()
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1036
|
+
await cl.load_assets()
|
|
1037
|
+
await cl.load_my_ads()
|
|
1038
|
+
r = await cl.ads_fresh(1, 1)
|
|
1039
|
+
print(r)
|
|
1040
1040
|
# await cl.asset_save(1, b)
|
|
1041
1041
|
# await cl.load_creds()
|
|
1042
1042
|
|
|
1043
|
-
await cl.ads_share()
|
|
1044
|
-
|
|
1045
|
-
ms = await models.Agent.filter(
|
|
1046
|
-
|
|
1047
|
-
).prefetch_related(
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
)
|
|
1054
|
-
{m.actor.exid: m.client(ecl) for m in ms}
|
|
1055
|
-
|
|
1056
|
-
await gather(
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
)
|
|
1060
|
-
# ensure_future(cl.start(True))
|
|
1061
|
-
# await cl.boost_acc()
|
|
1062
|
-
|
|
1063
|
-
# создание гонок по мои активным объявам:
|
|
1064
|
-
# for ma in cl.my_ads():
|
|
1065
|
-
# my_ad = await models.MyAd.get(ad__exid=ma.id).prefetch_related('ad__pms', 'ad__pair_side__pair')
|
|
1066
|
-
# race, _ = await models.Race.update_or_create(
|
|
1067
|
-
# {"started": True, "vm_filter": True, "target_place": 5},
|
|
1068
|
-
# road=my_ad
|
|
1069
|
-
# )
|
|
1070
|
-
|
|
1071
|
-
# for name in names:
|
|
1072
|
-
# s, _ = await models.Synonym.update_or_create(typ=SynonymType.name, txt=name)
|
|
1073
|
-
# await s.curs.add(rub.cur)
|
|
1074
|
-
|
|
1075
|
-
pauth = (await models.PmAgent[1]).auth
|
|
1076
|
-
papi = PayeerAPI(pauth["email"], pauth["api_id"], pauth["api_sec"])
|
|
1077
|
-
hist: dict = papi.history(count=1000)
|
|
1078
|
-
hist |= papi.history(count=1000, append=list(hist.keys())[-1])
|
|
1079
|
-
hist |= papi.history(count=1000, append=list(hist.keys())[-1])
|
|
1080
|
-
cl.hist = hist
|
|
1043
|
+
# await cl.ads_share()
|
|
1044
|
+
#
|
|
1045
|
+
# ms = await models.Agent.filter(
|
|
1046
|
+
# actor__ex_id=4, auth__isnull=False, status__gt=AgentStatus.off, actor__person__user__id__in=[3]
|
|
1047
|
+
# ).prefetch_related(
|
|
1048
|
+
# "actor__ex",
|
|
1049
|
+
# "actor__person__user__gmail",
|
|
1050
|
+
# "actor__my_ads__my_ad__race",
|
|
1051
|
+
# "actor__my_ads__pair_side__pair__cur",
|
|
1052
|
+
# "actor__my_ads__pms",
|
|
1053
|
+
# )
|
|
1054
|
+
# {m.actor.exid: m.client(ecl) for m in ms}
|
|
1055
|
+
#
|
|
1056
|
+
# await gather(
|
|
1057
|
+
# # create_task(cl.start()),
|
|
1058
|
+
# # create_task(cl.watch_payeer(mcs, abot)),
|
|
1059
|
+
# )
|
|
1060
|
+
# # ensure_future(cl.start(True))
|
|
1061
|
+
# # await cl.boost_acc()
|
|
1062
|
+
#
|
|
1063
|
+
# # создание гонок по мои активным объявам:
|
|
1064
|
+
# # for ma in cl.my_ads():
|
|
1065
|
+
# # my_ad = await models.MyAd.get(ad__exid=ma.id).prefetch_related('ad__pms', 'ad__pair_side__pair')
|
|
1066
|
+
# # race, _ = await models.Race.update_or_create(
|
|
1067
|
+
# # {"started": True, "vm_filter": True, "target_place": 5},
|
|
1068
|
+
# # road=my_ad
|
|
1069
|
+
# # )
|
|
1070
|
+
#
|
|
1071
|
+
# # for name in names:
|
|
1072
|
+
# # s, _ = await models.Synonym.update_or_create(typ=SynonymType.name, txt=name)
|
|
1073
|
+
# # await s.curs.add(rub.cur)
|
|
1074
|
+
#
|
|
1075
|
+
# pauth = (await models.PmAgent[1]).auth
|
|
1076
|
+
# papi = PayeerAPI(pauth["email"], pauth["api_id"], pauth["api_sec"])
|
|
1077
|
+
# hist: dict = papi.history(count=1000)
|
|
1078
|
+
# hist |= papi.history(count=1000, append=list(hist.keys())[-1])
|
|
1079
|
+
# hist |= papi.history(count=1000, append=list(hist.keys())[-1])
|
|
1080
|
+
# cl.hist = hist
|
|
1081
1081
|
|
|
1082
1082
|
# cl.completed_orders = await models.Order.filter(status=OrderStatus.completed, transfer__isnull=False).values_list(
|
|
1083
1083
|
# "exid", flat=True
|
|
@@ -19,13 +19,15 @@ class AdStatusReq(StrEnum):
|
|
|
19
19
|
|
|
20
20
|
IntStr = Annotated[str, BeforeValidator(str)]
|
|
21
21
|
Dec2Str = Annotated[str, BeforeValidator(lambda v: f"{round(v, 2):g}")]
|
|
22
|
+
Dec4Str = Annotated[str, BeforeValidator(lambda v: f"{round(v - 0.00049, 4):g}")]
|
|
22
23
|
NoneStr = Annotated[str, BeforeValidator(lambda v: f"{v or ''}")]
|
|
24
|
+
BoolIntStr = Annotated[Literal["0", "1"], BeforeValidator(lambda v: str(int(v)))]
|
|
23
25
|
|
|
24
26
|
|
|
25
27
|
class AdsReq(BaseModel):
|
|
26
28
|
tokenId: str = Field(validation_alias="coin_id")
|
|
27
29
|
currencyId: str = Field(validation_alias="cur_id")
|
|
28
|
-
side:
|
|
30
|
+
side: BoolIntStr = Field(validation_alias="is_sell") # 0 покупка, # 1 продажа
|
|
29
31
|
payment: list[str] = Field([], validation_alias="pm_ids") # int
|
|
30
32
|
size: str = Field("20", validation_alias="limit", coerce_numbers_to_str=True) # int
|
|
31
33
|
page: IntStr = "1" # int
|
|
@@ -120,7 +122,7 @@ class _MyAdEIn(RemapBase):
|
|
|
120
122
|
remark: NoneStr = Field("", validation_alias=AliasChoices("cond_txt", AliasPath("cond", "raw_txt")))
|
|
121
123
|
tradingPreferenceSet: TradingPreferenceSet = TradingPreferenceSet()
|
|
122
124
|
paymentIds: list[IntStr]
|
|
123
|
-
quantity:
|
|
125
|
+
quantity: Dec4Str # float
|
|
124
126
|
paymentPeriod: int = 15
|
|
125
127
|
|
|
126
128
|
@model_validator(mode="before")
|
|
@@ -140,6 +142,7 @@ class _MyAdEIn(RemapBase):
|
|
|
140
142
|
orderFinishNumberDay30=5,
|
|
141
143
|
registerTimeThreshold=15,
|
|
142
144
|
)
|
|
145
|
+
# out['quantity'] = f"{round(data.quantity-0.5*10**-data._coin_scale, data._coin_scale):g}"
|
|
143
146
|
return out
|
|
144
147
|
|
|
145
148
|
|
|
@@ -228,7 +231,12 @@ class Ad(BaseAd, RemapBase):
|
|
|
228
231
|
|
|
229
232
|
@model_validator(mode="after")
|
|
230
233
|
def set_filtered_flag(self):
|
|
231
|
-
self.filtered = bool(
|
|
234
|
+
self.filtered = bool(
|
|
235
|
+
self.tradingPreferenceSet
|
|
236
|
+
and self.tradingPreferenceSet.hasCompleteRateDay30
|
|
237
|
+
and self.tradingPreferenceSet.hasRegisterTime
|
|
238
|
+
and self.tradingPreferenceSet.hasOrderFinishNumberDay30
|
|
239
|
+
)
|
|
232
240
|
return self
|
|
233
241
|
|
|
234
242
|
|
|
@@ -124,6 +124,66 @@ class ExClient(BaseExClient): # Bybit client
|
|
|
124
124
|
return ads
|
|
125
125
|
|
|
126
126
|
|
|
127
|
+
curs = (
|
|
128
|
+
1,
|
|
129
|
+
2,
|
|
130
|
+
3,
|
|
131
|
+
4,
|
|
132
|
+
6,
|
|
133
|
+
8,
|
|
134
|
+
9,
|
|
135
|
+
10,
|
|
136
|
+
11,
|
|
137
|
+
12,
|
|
138
|
+
13,
|
|
139
|
+
14,
|
|
140
|
+
15,
|
|
141
|
+
17,
|
|
142
|
+
18,
|
|
143
|
+
19,
|
|
144
|
+
20,
|
|
145
|
+
21,
|
|
146
|
+
22,
|
|
147
|
+
28,
|
|
148
|
+
29,
|
|
149
|
+
30,
|
|
150
|
+
33,
|
|
151
|
+
36,
|
|
152
|
+
37,
|
|
153
|
+
40,
|
|
154
|
+
41,
|
|
155
|
+
43,
|
|
156
|
+
44,
|
|
157
|
+
47,
|
|
158
|
+
50,
|
|
159
|
+
51,
|
|
160
|
+
52,
|
|
161
|
+
56,
|
|
162
|
+
59,
|
|
163
|
+
65,
|
|
164
|
+
66,
|
|
165
|
+
68,
|
|
166
|
+
69,
|
|
167
|
+
73,
|
|
168
|
+
74,
|
|
169
|
+
77,
|
|
170
|
+
78,
|
|
171
|
+
80,
|
|
172
|
+
81,
|
|
173
|
+
82,
|
|
174
|
+
85,
|
|
175
|
+
88,
|
|
176
|
+
91,
|
|
177
|
+
101,
|
|
178
|
+
103,
|
|
179
|
+
107,
|
|
180
|
+
111,
|
|
181
|
+
112,
|
|
182
|
+
113,
|
|
183
|
+
119,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
|
|
127
187
|
async def main():
|
|
128
188
|
_ = await init_db(TORM, True)
|
|
129
189
|
ex = await Ex.get(name="Bybit")
|
|
@@ -131,8 +191,10 @@ async def main():
|
|
|
131
191
|
# await bot.start()
|
|
132
192
|
prx = PRX and "http://" + PRX
|
|
133
193
|
cl: ExClient = ex.client(proxy=prx)
|
|
134
|
-
await cl.set_coins(False)
|
|
135
|
-
|
|
194
|
+
# await cl.set_coins(False)
|
|
195
|
+
for cur in curs:
|
|
196
|
+
for coin in (1, 2, 3, 4):
|
|
197
|
+
await cl.set_rate(cur, coin)
|
|
136
198
|
# await cl.set_curs()
|
|
137
199
|
await cl.set_pms(bot)
|
|
138
200
|
await cl.set_pairs()
|
|
@@ -27,6 +27,10 @@ hot_ad_cond = "Банков НЕТ! Только XyncPay: @ex212 \n --- \n К
|
|
|
27
27
|
hot_ad_auto_msg = "Банков нет. Только XyncPay. Читайте условия! Отменяйте, если у вас нет XyncPay"
|
|
28
28
|
|
|
29
29
|
|
|
30
|
+
def more1perc(a: float, b: float):
|
|
31
|
+
return abs(a - b) / a > 0.01
|
|
32
|
+
|
|
33
|
+
|
|
30
34
|
async def search_messages(phrases_to_find) -> List[Dict[str, str]]:
|
|
31
35
|
_ = await init_db(TORM, True)
|
|
32
36
|
msgs = await models.Msg.all().values("txt")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|