xync-client 0.0.93.dev29__tar.gz → 0.0.95.dev0__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.
Files changed (124) hide show
  1. {xync_client-0.0.93.dev29/xync_client.egg-info → xync_client-0.0.95.dev0}/PKG-INFO +1 -1
  2. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/tests/TestAgent.py +3 -3
  3. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/tests/TestEx.py +5 -5
  4. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Abc/Agent.py +1 -1
  5. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Abc/Ex.py +23 -25
  6. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Abc/PmAgent.py +12 -5
  7. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Abc/xtype.py +2 -2
  8. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BingX/agent.py +23 -20
  9. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Bybit/InAgent.py +77 -40
  10. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Bybit/agent.py +20 -20
  11. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Htx/agent.py +3 -3
  12. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Htx/ex.py +1 -1
  13. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Payeer/__init__.py +56 -33
  14. xync_client-0.0.95.dev0/xync_client/Pms/Payeer/login.py +45 -0
  15. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Volet/__init__.py +2 -2
  16. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Xync/__main__.py +28 -138
  17. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/TgWallet/agent.py +15 -15
  18. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/TgWallet/ex.py +2 -2
  19. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/TgWallet/inAgent.py +3 -5
  20. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/pm_unifier.py +3 -3
  21. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0/xync_client.egg-info}/PKG-INFO +1 -1
  22. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client.egg-info/SOURCES.txt +0 -1
  23. xync_client-0.0.93.dev29/index.html +0 -397
  24. xync_client-0.0.93.dev29/xync_client/Pms/Payeer/login.py +0 -33
  25. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/.env.sample +0 -0
  26. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/.gitignore +0 -0
  27. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/.pre-commit-config.yaml +0 -0
  28. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/README.md +0 -0
  29. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/__init__.py +0 -0
  30. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/makefile +0 -0
  31. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/pyproject.toml +0 -0
  32. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/setup.cfg +0 -0
  33. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/tests/TestAsset.py +0 -0
  34. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/tests/TestOrder.py +0 -0
  35. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/tests/_todo_refact/Binance/test_binance.py +0 -0
  36. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/tests/_todo_refact/Bybit/test_bybit.py +0 -0
  37. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/tests/_todo_refact/Bybit/test_bybit_p2p.py +0 -0
  38. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/tests/_todo_refact/Gate/test_gate.py +0 -0
  39. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/tests/_todo_refact/Wallet/test_agent.py +0 -0
  40. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/tests/_todo_refact/Wallet/test_ex.py +0 -0
  41. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/tests/_todo_refact/__init__.py +0 -0
  42. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/tests/_todo_refact/_test_ex.py +0 -0
  43. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Abc/Asset.py +0 -0
  44. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Abc/Auth.py +0 -0
  45. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Abc/BaseTest.py +0 -0
  46. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Abc/Exception.py +0 -0
  47. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Abc/InAgent.py +0 -0
  48. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Abc/Order.py +0 -0
  49. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Binance/__init__.py +0 -0
  50. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Binance/binance_async.py +0 -0
  51. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Binance/earn_api.py +0 -0
  52. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Binance/etype/ad.py +0 -0
  53. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Binance/etype/pm.py +0 -0
  54. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Binance/ex.py +0 -0
  55. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Binance/exceptions.py +0 -0
  56. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Binance/sapi.py +0 -0
  57. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Binance/web_c2c.py +0 -0
  58. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BingX/__init__.py +0 -0
  59. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BingX/base.py +0 -0
  60. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BingX/etype/ad.py +0 -0
  61. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BingX/etype/pm.py +0 -0
  62. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BingX/ex.py +0 -0
  63. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BingX/req.mjs +0 -0
  64. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BingX/sign.js +0 -0
  65. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BitGet/__init__.py +0 -0
  66. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BitGet/agent.py +0 -0
  67. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BitGet/etype/ad.py +0 -0
  68. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BitGet/ex.py +0 -0
  69. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/BitPapa/ex.py +0 -0
  70. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Bybit/etype/ad.py +0 -0
  71. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Bybit/etype/cred.py +0 -0
  72. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Bybit/etype/order.py +0 -0
  73. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Bybit/ex.py +0 -0
  74. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Bybit/order.py +0 -0
  75. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Bybit/web_earn.py +0 -0
  76. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Bybit/web_p2p.py +0 -0
  77. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Bybit/ws.py +0 -0
  78. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Gate/etype/ad.py +0 -0
  79. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Gate/ex.py +0 -0
  80. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Gate/premarket.py +0 -0
  81. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Gmail/__init__.py +0 -0
  82. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Htx/earn.py +0 -0
  83. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Htx/etype/__init__.py +0 -0
  84. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Htx/etype/ad.py +0 -0
  85. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Htx/etype/cred.py +0 -0
  86. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Htx/etype/pm.py +0 -0
  87. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Htx/etype/test.py +0 -0
  88. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/KuCoin/etype/ad.py +0 -0
  89. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/KuCoin/etype/pm.py +0 -0
  90. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/KuCoin/ex.py +0 -0
  91. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/KuCoin/web.py +0 -0
  92. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Mexc/etype/ad.py +0 -0
  93. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Mexc/etype/pm.py +0 -0
  94. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Mexc/ex.py +0 -0
  95. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Okx/etype/ad.py +0 -0
  96. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Okx/etype/pm.py +0 -0
  97. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Okx/ex.py +0 -0
  98. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/.gitignore +0 -0
  99. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Alfa/__init__.py +0 -0
  100. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Alfa/state.json +0 -0
  101. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/MTS/__init__.py +0 -0
  102. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Ozon/__init__.py +0 -0
  103. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Payeer/.gitignore +0 -0
  104. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Payeer/api.py +0 -0
  105. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Sber/__init__.py +0 -0
  106. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Sber/utils.py +0 -0
  107. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Tinkoff/__init__.py +0 -0
  108. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Volet/_todo_req/req.mjs +0 -0
  109. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Volet/_todo_req/req.py +0 -0
  110. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Volet/api.py +0 -0
  111. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Volet/pl.py +0 -0
  112. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Xync/ed.py +0 -0
  113. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/Pms/Yandex/__init__.py +0 -0
  114. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/TgWallet/asset.py +0 -0
  115. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/TgWallet/auth.py +0 -0
  116. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/TgWallet/order.py +0 -0
  117. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/TgWallet/pyd.py +0 -0
  118. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/TgWallet/pyro.py +0 -0
  119. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/TgWallet/web.py +0 -0
  120. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/__init__.py +0 -0
  121. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client/loader.py +0 -0
  122. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client.egg-info/dependency_links.txt +0 -0
  123. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client.egg-info/requires.txt +0 -0
  124. {xync_client-0.0.93.dev29 → xync_client-0.0.95.dev0}/xync_client.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xync-client
3
- Version: 0.0.93.dev29
3
+ Version: 0.0.95.dev0
4
4
  Author-email: Mike Artemiev <mixartemev@gmail.com>
5
5
  Project-URL: Homepage, https://gitlab.com/XyncNet/client
6
6
  Project-URL: Repository, https://gitlab.com/XyncNet/client
@@ -3,7 +3,7 @@ import logging
3
3
  import pytest
4
4
  from tortoise.functions import Count
5
5
  from xync_schema.enums import ExStatus, ExAction, UserStatus
6
- from xync_schema.models import Ex, ExStat, Ad, Coin, Cur, Pmcur, Cred, CredEx, Actor, Person
6
+ from xync_schema.models import Ex, ExStat, Ad, Coin, Cur, PmCur, Cred, CredEx, Actor, Person
7
7
  from xync_schema.xtype import BaseAd
8
8
 
9
9
  from xync_client.Abc.BaseTest import BaseTest
@@ -32,9 +32,9 @@ class TestAgent(BaseTest):
32
32
  # 26
33
33
  async def test_cred_new(self, clients: list[tuple[BaseAgentClient, BaseAgentClient]]):
34
34
  for maker, taker in clients:
35
- pmcur = await Pmcur.filter(pm__pmexs__ex=taker.actor.ex, cur__ticker="RUB", pm__norm="payeer").first()
35
+ pmcur = await PmCur.filter(pm__pmexs__ex=taker.actor.ex, cur__ticker="RUB", pm__norm="payeer").first()
36
36
  cred = await Cred.create(person_id=taker.actor.person_id, name="Tst", detail="79990001234", pmcur=pmcur)
37
- # await cred.banks.add(await PmexBank.get(exid="mts"), await PmexBank.get(exid="sberbankru"))
37
+ # await cred.banks.add(await PmExBank.get(exid="mts"), await PmExBank.get(exid="sberbankru"))
38
38
  cred_new: CredEx = await taker.cred_new(cred)
39
39
  ok = isinstance(cred_new, CredEx)
40
40
  t, _ = await ExStat.update_or_create({"ok": ok}, ex=taker.actor.ex, action=ExAction.cred_new)
@@ -104,8 +104,8 @@ class TestEx(BaseTest):
104
104
  # 24
105
105
  async def test_ads(self, clients: list[BaseExClient]):
106
106
  for client in clients:
107
- cur = await models.Curex.filter(cur__ticker="EUR", ex=client.ex).first().values_list("exid", flat=True)
108
- coin = await models.Coinex.filter(coin__ticker="USDT", ex=client.ex).first().values_list("exid", flat=True)
107
+ cur = await models.CurEx.filter(cur__ticker="EUR", ex=client.ex).first().values_list("exid", flat=True)
108
+ coin = await models.CoinEx.filter(coin__ticker="USDT", ex=client.ex).first().values_list("exid", flat=True)
109
109
  ads: list[BaseAd] = await client.ads(coin, cur, False)
110
110
  ok = self.is_list_of_objects(ads, BaseAd)
111
111
  t, _ = await models.ExStat.update_or_create({"ok": ok}, ex=client.ex, action=ExAction.ads)
@@ -123,10 +123,10 @@ class TestEx(BaseTest):
123
123
  continue
124
124
  for race in races:
125
125
  # получаем данные направления текущей гонки
126
- coinex = await models.Coinex.get(ex=client.ex, coin_id=race.road.ad.pair_side.pair.coin_id)
127
- curex = await models.Curex.get(ex=client.ex, cur_id=race.road.ad.pair_side.pair.cur_id)
126
+ coinex = await models.CoinEx.get(ex=client.ex, coin_id=race.road.ad.pair_side.pair.coin_id)
127
+ curex = await models.CurEx.get(ex=client.ex, cur_id=race.road.ad.pair_side.pair.cur_id)
128
128
  pm_ids = [pm.id for pm in race.road.ad.pms]
129
- pmex_exids = await models.Pmex.filter(ex=client.ex, pm_id__in=pm_ids).values_list("exid", flat=True)
129
+ pmex_exids = await models.PmEx.filter(ex=client.ex, pm_id__in=pm_ids).values_list("exid", flat=True)
130
130
  # получаем объявления по этому направлению
131
131
  ads = await client.ads(coinex.exid, curex.exid, race.road.ad.pair_side.is_sell, pmex_exids)
132
132
  # if race.vm_filter:
@@ -128,5 +128,5 @@ class BaseAgentClient(HttpClient):
128
128
  # credex_in = models.CredEx.validate({"exid": cred_in.id, "cred_id": cred_db.id})
129
129
  # credex_db, _ = await models.CredEx.update_or_create(**credex_in.df_unq())
130
130
  # if banks: # only for SBP
131
- # await cred_db.banks.add(*[await PmexBank.get(exid=b) for b in banks])
131
+ # await cred_db.banks.add(*[await PmExBank.get(exid=b) for b in banks])
132
132
  # return True
@@ -36,7 +36,7 @@ class BaseExClient(HttpClient):
36
36
  super().__init__(getattr(ex, attr), headers, cookies, proxy and proxy.str())
37
37
 
38
38
  @abstractmethod
39
- def pm_type_map(self, typ: models.Pmex) -> str: ...
39
+ def pm_type_map(self, typ: models.PmEx) -> str: ...
40
40
 
41
41
  # 19: Список поддерживаемых валют тейкера
42
42
  @abstractmethod
@@ -87,7 +87,7 @@ class BaseExClient(HttpClient):
87
87
  async def countries(self) -> list[Struct]:
88
88
  return []
89
89
 
90
- # Импорт валют Cur-ов (с Curex-ами)
90
+ # Импорт валют Cur-ов (с CurEx-ами)
91
91
  async def set_curs(self, cookies: dict = None) -> bool:
92
92
  # Curs
93
93
  cur_pyds: dict[str, CurEx] = await self.curs()
@@ -96,14 +96,12 @@ class BaseExClient(HttpClient):
96
96
  for exid, cur_pyd in cur_pyds.items()
97
97
  }
98
98
  curexs = [
99
- models.Curex(**c.model_dump(exclude_none=True), cur=curs[c.exid], ex=self.ex) for c in cur_pyds.values()
99
+ models.CurEx(**c.model_dump(exclude_none=True), cur=curs[c.exid], ex=self.ex) for c in cur_pyds.values()
100
100
  ]
101
- # Curex
102
- await models.Curex.bulk_create(
103
- curexs, update_fields=["minimum", "rounding_scale"], on_conflict=["cur_id", "ex_id"]
104
- )
101
+ # CurEx
102
+ await models.CurEx.bulk_create(curexs, update_fields=["minimum", "scale"], on_conflict=["cur_id", "ex_id"])
105
103
 
106
- # Импорт Pm-ов (с Pmcur-, Pmex- и Pmcurex-ами) и валют (с Curex-ами) с биржи в бд
104
+ # Импорт Pm-ов (с PmCur-, PmEx- и Pmcurex-ами) и валют (с CurEx-ами) с биржи в бд
107
105
  async def set_pms(self, cookies: dict = None) -> bool:
108
106
  if cookies:
109
107
  self.session.cookie_jar.update_cookies(cookies)
@@ -134,19 +132,19 @@ class BaseExClient(HttpClient):
134
132
  logging.warning(f"Pm: '{pmex.name}' duplicated with ids {prev[0]}: {k} on {self.ex.name}")
135
133
  # новый Pm не добавляем, а берем старый с этим названием
136
134
  pm_ = pms.get(prev[0], await models.Pm.get_or_none(norm=prev[1], country_id=country_id))
137
- # и добавляем Pmex для него
138
- await models.Pmex.update_or_create({"name": pmex.name}, ex=self.ex, exid=k, pm=pm_)
135
+ # и добавляем PmEx для него
136
+ await models.PmEx.update_or_create({"name": pmex.name}, ex=self.ex, exid=k, pm=pm_)
139
137
  elif (
140
138
  prev[1] == pmu.norm and pmu.country == prev[3]
141
139
  ): # 2 разных оригинальных имени на этой бирже совпали при нормализации
142
140
  logging.error(
143
141
  f"Pm: {pmex.name}&{prev[2]} overnormd as {pmu.norm} with ids {prev[0]}: {k} on {self.ex.name}"
144
142
  )
145
- # новый Pm не добавляем, только Pmex для него
143
+ # новый Pm не добавляем, только PmEx для него
146
144
  # новый Pm не добавляем, а берем старый с этим названием
147
145
  pm_ = pms.get(prev[0], await models.Pm.get_or_none(norm=prev[1], country_id=country_id))
148
- # и добавляем.обновляем Pmex для него
149
- await models.Pmex.update_or_create({"pm": pm_}, ex=self.ex, exid=k, name=pmex.name)
146
+ # и добавляем.обновляем PmEx для него
147
+ await models.PmEx.update_or_create({"pm": pm_}, ex=self.ex, exid=k, name=pmex.name)
150
148
  else:
151
149
  pmin = models.Pm.validate({**pmu.model_dump(), "country_id": country_id, "typ": pmex.typ})
152
150
  try:
@@ -154,14 +152,14 @@ class BaseExClient(HttpClient):
154
152
  except (MultipleObjectsReturned, IntegrityError) as e:
155
153
  raise e
156
154
  prev = k, pmu.norm, pmex.name, pmu.country
157
- await models.Pmcur.update_or_create( # todo: NA HU YA???
155
+ await models.PmCur.update_or_create( # todo: NA HU YA???
158
156
  cur=await models.Cur.get(ticker="THB"), pm=await models.Pm.get(norm="cash in person")
159
157
  )
160
158
 
161
159
  # Pmexs
162
160
  async with ClientSession(headers=getattr(self, "logo_headers", None)) as ss:
163
161
  pmexs = [
164
- models.Pmex(
162
+ models.PmEx(
165
163
  # todo: refact logo
166
164
  exid=k,
167
165
  ex=self.ex,
@@ -172,13 +170,13 @@ class BaseExClient(HttpClient):
172
170
  for k, pm in pms.items()
173
171
  ]
174
172
 
175
- await models.Pmex.bulk_create(pmexs, on_conflict=["ex_id", "exid"], update_fields=["pm_id", "logo_id", "name"])
176
- # Pmex banks
173
+ await models.PmEx.bulk_create(pmexs, on_conflict=["ex_id", "exid"], update_fields=["pm_id", "logo_id", "name"])
174
+ # PmEx banks
177
175
  for k, pmex in pmexs_epyds.items():
178
176
  if banks := pmex.banks:
179
- pmex = await models.Pmex.get(ex=self.ex, exid=k) # pm=pms[k],
177
+ pmex = await models.PmEx.get(ex=self.ex, exid=k) # pm=pms[k],
180
178
  for b in banks:
181
- await models.PmexBank.update_or_create({"name": b.name}, exid=b.exid, pmex=pmex)
179
+ await models.PmExBank.update_or_create({"name": b.name}, exid=b.exid, pmex=pmex)
182
180
 
183
181
  cur2pms = await self.cur_pms_map()
184
182
  # # Link PayMethods with currencies
@@ -186,13 +184,13 @@ class BaseExClient(HttpClient):
186
184
  for cur_id, exids in cur2pms.items():
187
185
  for exid in exids:
188
186
  if not (pm_id := pms.get(exid) and pms[exid].id):
189
- if pmex := await models.Pmex.get_or_none(ex=self.ex, exid=exid):
187
+ if pmex := await models.PmEx.get_or_none(ex=self.ex, exid=exid):
190
188
  pm_id = pmex.pm_id
191
189
  else:
192
190
  logging.critical(f"For cur {cur_id} not found pm#{exid}")
193
191
  continue
194
192
  if cur_db := curs.get(cur_id):
195
- pmcurs.add((await models.Pmcur.update_or_create(cur=cur_db, pm_id=pm_id))[0])
193
+ pmcurs.add((await models.PmCur.update_or_create(cur=cur_db, pm_id=pm_id))[0])
196
194
  # pmcurexs = [Pmcurex(pmcur=pmcur, ex=self.ex) for pmcur in pmcurs]
197
195
  # await Pmcurex.bulk_create(pmcurexs)
198
196
  return True
@@ -206,7 +204,7 @@ class BaseExClient(HttpClient):
206
204
  return await self.file_upsert(url, ss)
207
205
  return file
208
206
 
209
- # Импорт монет (с Coinex-ами) с биржи в бд
207
+ # Импорт монет (с CoinEx-ами) с биржи в бд
210
208
  async def set_coins(self):
211
209
  coins: dict[str, CoinEx] = await self.coins()
212
210
  coins_db: dict[int, models.Coin] = {
@@ -215,10 +213,10 @@ class BaseExClient(HttpClient):
215
213
  )[0]
216
214
  for c in coins.values()
217
215
  }
218
- coinexs: list[models.Coinex] = [
219
- models.Coinex(coin=coins_db[c.exid], ex=self.ex, exid=c.exid, minimum=c.minimum) for c in coins.values()
216
+ coinexs: list[models.CoinEx] = [
217
+ models.CoinEx(coin=coins_db[c.exid], ex=self.ex, exid=c.exid, minimum=c.minimum) for c in coins.values()
220
218
  ]
221
- await models.Coinex.bulk_create(coinexs, update_fields=["minimum"], on_conflict=["coin_id", "ex_id"])
219
+ await models.CoinEx.bulk_create(coinexs, update_fields=["minimum"], on_conflict=["coin_id", "ex_id"])
222
220
  return True
223
221
 
224
222
  # Импорт пар биржи в бд
@@ -1,4 +1,6 @@
1
1
  from abc import abstractmethod, ABCMeta
2
+ from asyncio import get_running_loop
3
+ from datetime import datetime, timedelta
2
4
  from decimal import Decimal
3
5
  from enum import StrEnum
4
6
 
@@ -25,6 +27,8 @@ class PmAgentClient(metaclass=ABCMeta):
25
27
  bot: FileClient
26
28
  page: Page
27
29
  pages: type(StrEnum) = Pages
30
+ last_page: int = 0
31
+ last_active: datetime = datetime.now()
28
32
  _is_started: bool = False
29
33
 
30
34
  async def start(self, pw: Playwright, headed: bool = False) -> "PmAgentClient":
@@ -49,15 +53,18 @@ class PmAgentClient(metaclass=ABCMeta):
49
53
  if not self.page.url.startswith(self.pages.SEND): # Если в итоге не удалось попасть на отправку
50
54
  await self.bot.send(self.norm + " not logged in!", self.uid, photo=await self.page.screenshot())
51
55
  raise LoginFailedException(f"User {self.agent.user_id} has not logged in")
52
- # loop = get_running_loop()
53
- # loop.create_task(self._idle()) # Бесконечно пасёмся в фоне на странице отправки, что бы куки не протухли
56
+ loop = get_running_loop()
57
+ self.last_active = datetime.now()
58
+ loop.create_task(self._idle()) # Бесконечно пасёмся в фоне на странице отправки, что бы куки не протухли
54
59
  self._is_started = True
55
60
  return self
56
61
 
57
62
  async def _idle(self): # todo: не мешать другим процессам, обновлять на другой вкладке?
58
63
  while (await User.get(username_id=self.uid)).status >= UserStatus.ACTIVE:
59
- await self.page.wait_for_timeout(30 * 1000)
60
- await self.page.reload()
64
+ await self.page.wait_for_timeout(15 * 1000)
65
+ if self.last_active < datetime.now() - timedelta(seconds=20):
66
+ await self.page.reload()
67
+ self.last_active = datetime.now()
61
68
  await self.bot.send(self.norm + " stoped", self.uid)
62
69
  await self.stop()
63
70
 
@@ -75,7 +82,7 @@ class PmAgentClient(metaclass=ABCMeta):
75
82
  async def _login(self): ...
76
83
 
77
84
  @abstractmethod
78
- async def send(self, dest, amount: int, cur: str) -> tuple[int, bytes]: ...
85
+ async def send(self, dest, amount: int, cur: str) -> tuple[int, bytes, float]: ...
79
86
 
80
87
  @abstractmethod # проверка поступления определенной суммы за последние пол часа (минимум), return точную сумму
81
88
  async def check_in(self, amount: int | Decimal | float, cur: str, tid: str | int = None) -> float | None: ...
@@ -4,7 +4,7 @@ from pydantic import BaseModel, model_validator
4
4
  from x_model.types import BaseUpd
5
5
  from xync_schema.enums import PmType
6
6
  from xync_schema.models import Country, Pm, Ex
7
- from xync_schema.xtype import PmexBank
7
+ from xync_schema.xtype import PmExBank
8
8
 
9
9
  from xync_client.pm_unifier import PmUni
10
10
 
@@ -17,7 +17,7 @@ MapOfIdsList = dict[int | str, list[int | str]]
17
17
  class PmTrait:
18
18
  typ: PmType | None = None
19
19
  logo: str | None = None
20
- banks: list[PmexBank] | None = None
20
+ banks: list[PmExBank] | None = None
21
21
 
22
22
 
23
23
  class PmEx(BaseModel, PmTrait):
@@ -2,7 +2,8 @@ from xync_client.Abc.Agent import BaseAgentClient
2
2
  from xync_schema.pydantic import FiatNew
3
3
  from xync_schema.models import Cur, Fiat
4
4
  from xync_client.Abc.Base import DictOfDicts
5
- from xync_schema.models import Cur, Coin, OrderStatus, Pmex, Fiat, Ad, Pmcur, Fiatex
5
+ from xync_schema.models import Coin, OrderStatus
6
+
6
7
 
7
8
  class AgentClient(BaseAgentClient):
8
9
  headers = {
@@ -37,18 +38,20 @@ class AgentClient(BaseAgentClient):
37
38
  }
38
39
 
39
40
  # 0: Получшение заявок за заданное время, в статусе, по валюте, монете
40
- async def get_orders(self, status: OrderStatus = OrderStatus.created, coin: Coin = None, cur: Cur = None, is_sell: bool = None):
41
+ async def get_orders(
42
+ self, status: OrderStatus = OrderStatus.created, coin: Coin = None, cur: Cur = None, is_sell: bool = None
43
+ ):
41
44
  params = {
42
- 'pageId': '0',
43
- 'pageSize': '10',
44
- 'messageStatus': '0',
45
- 'orderType': '1',
46
- 'orderStatus': '',
47
- 'fiat': '',
48
- 'searchKeyword': '',
49
- 'tradeType': '',
50
- 'beginTime': '1706475600000',
51
- 'endTime': '1738184399999',
45
+ "pageId": "0",
46
+ "pageSize": "10",
47
+ "messageStatus": "0",
48
+ "orderType": "1",
49
+ "orderStatus": "",
50
+ "fiat": "",
51
+ "searchKeyword": "",
52
+ "tradeType": "",
53
+ "beginTime": "1706475600000",
54
+ "endTime": "1738184399999",
52
55
  }
53
56
  order = await self._get("/api/c2c/v2/order/list", params=params)
54
57
  return order["data"]["result"]
@@ -56,14 +59,14 @@ class AgentClient(BaseAgentClient):
56
59
  # 1: [T] Запрос на старт сделки
57
60
  async def order_request(self, ad_id: int, amount: float):
58
61
  json_data = {
59
- 'advertNo': f'{ad_id}',
60
- 'asset': 'USDT',
61
- 'fiat': 'RUB',
62
- 'type': 1,
63
- 'userPrice': 103,
64
- 'areaType': 2,
65
- 'amount': f'{amount}',
66
- 'paymentMethodId': 110,
62
+ "advertNo": f"{ad_id}",
63
+ "asset": "USDT",
64
+ "fiat": "RUB",
65
+ "type": 1,
66
+ "userPrice": 103,
67
+ "areaType": 2,
68
+ "amount": f"{amount}",
69
+ "paymentMethodId": 110,
67
70
  }
68
71
  order = await self._post("/api/c2c/v1/order/create", json=json_data)
69
72
  if order["data"]:
@@ -2,7 +2,7 @@ import json
2
2
  import logging
3
3
  import re
4
4
  from datetime import datetime, timezone
5
- # from uuid import uuid4
5
+ from uuid import uuid4
6
6
 
7
7
  import websockets
8
8
  from asyncio import run
@@ -10,6 +10,9 @@ from decimal import Decimal
10
10
 
11
11
  from playwright.async_api import async_playwright
12
12
  from pyro_client.client.file import FileClient
13
+ from tortoise.transactions import in_transaction
14
+ from xync_schema.models import CredEx
15
+
13
16
  from xync_client.Abc.PmAgent import PmAgentClient
14
17
  from xync_schema import models
15
18
  from xync_schema.enums import UserStatus, OrderStatus
@@ -89,17 +92,22 @@ class InAgentClient(BaseInAgentClient):
89
92
  dest = order.paymentTermList[0].accountNo
90
93
  if not re.match(r"^P\d{8,10}$", dest):
91
94
  continue
92
- await order_db.fetch_related("cred__pmcur__cur")
93
- if order_db.status in (OrderStatus.created, OrderStatus.requested):
94
- await self.send_payment(order_db, dest)
95
- ...
95
+ await order_db.fetch_related("ad__pair_side__pair", "cred__pmcur__cur")
96
+ await self.send_payment(order_db, dest)
96
97
  case StatusApi.wait_for_buyer:
97
98
  if upd.side == 0: # ждем когда покупатель оплатит
98
99
  if not (pmacdx := await self.get_pma_by_cdex(order)):
99
100
  continue
100
101
  pma, cdx = pmacdx
101
- am, tid = pma.check_in(Decimal(order.amount), cdx.cred.pmcur.cur.ticker)
102
+ am, tid = pma.check_in(
103
+ Decimal(order.amount),
104
+ cdx.cred.pmcur.cur.ticker,
105
+ datetime.fromtimestamp(float(order.createDate) / 1000),
106
+ )
102
107
  if not tid:
108
+ logging.info(
109
+ f"Order {order.id} created at {order.createDate}, not paid yet"
110
+ )
103
111
  continue
104
112
  t, is_new = await models.Transfer.update_or_create(
105
113
  dict(
@@ -109,15 +117,26 @@ class InAgentClient(BaseInAgentClient):
109
117
  order=order_db,
110
118
  pmid=tid,
111
119
  )
112
- if is_new:
120
+ if not is_new:
121
+ continue
122
+ await order_db.fetch_related("ad__pair_side__pair")
123
+ async with in_transaction():
124
+ # добавляем остаток монеты
125
+ ass = await models.Asset.get(
126
+ addr__coin_id=order_db.ad.pair_side.pair.coin_id,
127
+ addr__actor=self.agent_client.actor,
128
+ )
129
+ ass.free -= float(order_db.amount / order_db.ad.price)
130
+ await ass.save(update_fields=["free"])
131
+ # обновляем остаток валюты
132
+ fiat = await models.Fiat.get(cred_id=order_db.cred_id)
133
+ fiat.amount += order_db.amount
134
+ await fiat.save(update_fields=["amount"])
135
+ # отправляем деньги
113
136
  self.agent_client.api.release_assets(orderId=upd.id)
114
137
  logging.info(
115
138
  f"Order {order.id} created, paid before #{tid}:{am} at {order.createDate}, and RELEASED at {datetime.now()}"
116
139
  )
117
- else:
118
- logging.info(
119
- f"Order {order.id} created at {order.createDate} but no paid yet"
120
- )
121
140
  elif upd.side == 1: # я покупатель - ждем мою оплату
122
141
  continue # logging.warning(f"Order {order.id} PAID at {datetime.now()}: {int_am}")
123
142
  else:
@@ -173,7 +192,7 @@ class InAgentClient(BaseInAgentClient):
173
192
  upd = Receive.model_validate(data["data"])
174
193
  if order_db := await models.Order.get_or_none(
175
194
  exid=upd.orderId, ad__maker__ex=self.agent_client.actor.ex
176
- ).prefetch_related("ad__pair_side", "cred__pmcur__cur"):
195
+ ).prefetch_related("ad__pair_side__pair", "cred__pmcur__cur"):
177
196
  im_taker = order_db.taker_id == self.agent_client.actor.id
178
197
  im_buyer = order_db.ad.pair_side.is_sell == im_taker
179
198
  if order_db.ad.auto_msg != upd.message and upd.roleType not in ("sys", "alarm"):
@@ -188,9 +207,7 @@ class InAgentClient(BaseInAgentClient):
188
207
  if not upd.message:
189
208
  ...
190
209
  if im_buyer and re.match(r"^P\d{8,10}$", upd.message):
191
- if order_db.status in (OrderStatus.created, OrderStatus.requested):
192
- await self.send_payment(order_db, upd.message)
193
- ...
210
+ await self.send_payment(order_db, upd.message)
194
211
  case "READ":
195
212
  upd = Read.model_validate(data["data"])
196
213
  # if upd.status not in (StatusWs.created, StatusWs.canceled, 10, StatusWs.completed):
@@ -227,33 +244,53 @@ class InAgentClient(BaseInAgentClient):
227
244
  if not upd:
228
245
  logging.warning(data, "NOT PROCESSED UPDATE")
229
246
 
230
- async def send_payment(self, order_db: models.Order, dest) -> tuple[PmAgentClient, models.CredEx]:
247
+ async def send_payment(self, order_db: models.Order, dest):
248
+ if order_db.status not in (OrderStatus.created, OrderStatus.requested):
249
+ return
231
250
  int_am = int(float(order_db.amount))
232
251
  pma, cur = await self.get_pma_by_pmex(order_db)
233
- tid, img = await pma.send(dest=dest, amount=int_am, cur=cur)
234
- t, is_new = await models.Transfer.update_or_create(
235
- {"amount": int_am * 100},
236
- order=order_db,
237
- pmid=tid,
238
- )
239
- pmex = await models.Pmex.get(pm_id=order_db.cred.pmcur.pm_id, ex=self.agent_client.actor.ex)
240
- credex = await models.CredEx.get(cred=order_db.cred, ex=self.agent_client.actor.ex)
241
- self.agent_client.api.mark_as_paid(
242
- orderId=str(order_db.exid),
243
- paymentType=pmex.exid, # pmex.exid
244
- paymentId=str(credex.exid), # credex.exid
245
- )
246
- order_db.status = OrderStatus.paid
247
- order_db.payed_at = datetime.now(timezone.utc)
248
- await order_db.save()
249
- # models.Fiat.get()
250
- # if res := self.agent_client.api.upload_chat_file(upload_file=f"tmp/{dest}.png").get('result'):
251
- # self.agent_client.api.send_chat_message(
252
- # orderId=str(order_db.exid), contentType="pic", message=res['url'], msgUuid=uuid4().hex
253
- # )
254
- logging.warning(f"Order {order_db.exid} PAID at {datetime.now()}: {int_am}")
252
+ async with in_transaction():
253
+ # отмечаем ордер на бирже "оплачен"
254
+ pmex = await models.PmEx.get(pm_id=order_db.cred.pmcur.pm_id, ex=self.agent_client.actor.ex)
255
+ credex = await models.CredEx.get(cred=order_db.cred, ex=self.agent_client.actor.ex)
256
+ self.agent_client.api.mark_as_paid(
257
+ orderId=str(order_db.exid),
258
+ paymentType=pmex.exid, # pmex.exid
259
+ paymentId=str(credex.exid), # credex.exid
260
+ )
261
+ # проверяем не отправляли ли мы уже перевод по этому ордеру
262
+ if t := await models.Transfer.get_or_none(order=order_db, amount=int_am):
263
+ await pma.bot.send(f"Order# {order_db.exid}: Double send {int_am}{cur} to {dest} #{t.pmid}!")
264
+ raise Exception(f"Order# {order_db.exid}: Double send {int_am}{cur} to {dest} #{t.pmid}!")
265
+
266
+ # ставим в бд статус "оплачен"
267
+ order_db.status = OrderStatus.paid
268
+ order_db.payed_at = datetime.now(timezone.utc)
269
+ await order_db.save()
270
+ # добавляем остаток монеты
271
+ ass = await models.Asset.get(
272
+ addr__coin_id=order_db.ad.pair_side.pair.coin_id, addr__actor=self.agent_client.actor
273
+ )
274
+ ass.free += float(order_db.amount / order_db.ad.price)
275
+ await ass.save(update_fields=["free"])
276
+ # отправляем деньги
277
+ tid, img, rest_amount = await pma.send(dest=dest, amount=int_am, cur=cur)
278
+ # создаем перевод в бд
279
+ t, _ = await models.Transfer.update_or_create(
280
+ {"amount": int_am * 100},
281
+ order=order_db,
282
+ pmid=tid,
283
+ )
284
+ # обновляем остаток валюты
285
+ await models.Fiat.update_or_create({"amount": rest_amount}, cred_id=order_db.cred_id)
286
+ # отправляем продавцу чек
287
+ if res := self.agent_client.api.upload_chat_file(upload_file=f"tmp/{dest}.png").get("result"):
288
+ self.agent_client.api.send_chat_message(
289
+ orderId=str(order_db.exid), contentType="pic", message=res["url"], msgUuid=uuid4().hex
290
+ )
291
+ logging.info(f"Order {order_db.exid} PAID at {datetime.now()}: {int_am}!")
255
292
 
256
- async def get_pma_by_cdex(self, order: OrderFull) -> tuple[PmAgentClient, models.CredEx]:
293
+ async def get_pma_by_cdex(self, order: OrderFull) -> tuple[PmAgentClient | None, CredEx] | None:
257
294
  cdxs = await models.CredEx.filter(
258
295
  ex=self.agent_client.ex_client.ex,
259
296
  exid__in=[ptl.id for ptl in order.paymentTermList],
@@ -261,7 +298,7 @@ class InAgentClient(BaseInAgentClient):
261
298
  ).prefetch_related("cred__pmcur__cur")
262
299
  pmas = [pma for cdx in cdxs if (pma := self.pmacs.get(cdx.cred.pmcur.pm_id))]
263
300
  if not len(pmas):
264
- logging.error(order.paymentTermList, f"No pm_agents for {order.paymentTermList[0].paymentType}")
301
+ raise Exception(order.paymentTermList, f"No pm_agents for {order.paymentTermList[0].paymentType}")
265
302
  elif len(pmas) > 1:
266
303
  logging.error(order.paymentTermList, f">1 pm_agents for {cdxs[0].cred.pmcur.pm_id}")
267
304
  else: