xync-db 0.0.2__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_db/__init__.py +28 -0
- xync_db/config.py +18 -0
- xync_db/enums.py +311 -0
- xync_db/exceptions.py +18 -0
- xync_db/graph.py +65 -0
- xync_db/logo.png +0 -0
- xync_db/models/CLAUDE.md +125 -0
- xync_db/models/__init__.py +1888 -0
- xync_db/shared.py +70 -0
- xync_db/typs/__init__.py +40 -0
- xync_db/typs/db/ad.py +76 -0
- xync_db/typs/db/common.py +25 -0
- xync_db/typs/db/order.py +38 -0
- xync_db-0.0.2.dist-info/METADATA +34 -0
- xync_db-0.0.2.dist-info/RECORD +16 -0
- xync_db-0.0.2.dist-info/WHEEL +4 -0
xync_db/__init__.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from os import getenv as env
|
|
2
|
+
|
|
3
|
+
from dotenv import load_dotenv
|
|
4
|
+
|
|
5
|
+
load_dotenv()
|
|
6
|
+
|
|
7
|
+
TORM = {
|
|
8
|
+
"connections": {"default": env("DB_URL")},
|
|
9
|
+
"apps": {"models": {"models": ["xync_db.models"]}},
|
|
10
|
+
"use_tz": False,
|
|
11
|
+
"timezone": "UTC",
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
async def main():
|
|
16
|
+
import logging
|
|
17
|
+
from logging import DEBUG
|
|
18
|
+
|
|
19
|
+
from x_model import init_db
|
|
20
|
+
|
|
21
|
+
logging.basicConfig(level=DEBUG)
|
|
22
|
+
await init_db(TORM, create_tables=True)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
if __name__ == "__main__":
|
|
26
|
+
from asyncio import run
|
|
27
|
+
|
|
28
|
+
run(main())
|
xync_db/config.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Tortoise ORM configuration. Used by the CLI and by service lifecycle hooks."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
POSTGRES_DSN = os.getenv("POSTGRES_DSN", "postgres://xync:xync@localhost:5432/xync")
|
|
8
|
+
|
|
9
|
+
TORTOISE_ORM: dict = {
|
|
10
|
+
"connections": {"default": POSTGRES_DSN},
|
|
11
|
+
"apps": {
|
|
12
|
+
"models": {
|
|
13
|
+
"models": ["xync_db.models", "xync_db.migrations.models"],
|
|
14
|
+
"default_connection": "default",
|
|
15
|
+
"migrations": "xync_db.migrations.models",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
}
|
xync_db/enums.py
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
from enum import IntEnum
|
|
2
|
+
|
|
3
|
+
ZERO_TS = 1770000000 # Feb 02 2026 02:40:00 (UTC)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class PersonStatus(IntEnum):
|
|
7
|
+
VIP = 2
|
|
8
|
+
DEFAULT = 1
|
|
9
|
+
ANONYMOUS = 0
|
|
10
|
+
USER_DEF = -1
|
|
11
|
+
BLOCKED = -2
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Side(IntEnum):
|
|
15
|
+
BUY = 0
|
|
16
|
+
SALE = 1
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class PriceType(IntEnum):
|
|
20
|
+
FIX = 0
|
|
21
|
+
FLOAT = 1
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class TransactionStatus(IntEnum):
|
|
25
|
+
request = 0 # no proof
|
|
26
|
+
signed = 1 # in proof: sender sign for transfer
|
|
27
|
+
verified = 2 # in proof: validator sign for transfer is valid
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class LinkType(IntEnum):
|
|
31
|
+
ref = 0 # open or trusted
|
|
32
|
+
request = 1 # open or personalized
|
|
33
|
+
receipt = 2 # signed or verified
|
|
34
|
+
contract = 3 # todo
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class UserStatus(IntEnum):
|
|
38
|
+
SLEEP = 0
|
|
39
|
+
PAY = 1
|
|
40
|
+
HOT_PARTNER = 2 # partner
|
|
41
|
+
XYNC_TEAM = 3
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class AdStatus(IntEnum):
|
|
45
|
+
defActive = 0
|
|
46
|
+
active = 1
|
|
47
|
+
soldOut = 2
|
|
48
|
+
old = 3
|
|
49
|
+
notFound = 9
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class HotStatus(IntEnum):
|
|
53
|
+
closed = 0
|
|
54
|
+
opened = 1
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class OrderStatus(IntEnum):
|
|
58
|
+
created = 1
|
|
59
|
+
paid = 2
|
|
60
|
+
completed = 3
|
|
61
|
+
cancel_requested_by_seller = 4
|
|
62
|
+
canceled = 5
|
|
63
|
+
appealed_by_seller = 6
|
|
64
|
+
appealed_by_buyer = 7
|
|
65
|
+
appeal_disputed = 8
|
|
66
|
+
# todo: 8T - один вирт экшн на бездействие обеих сторон, а 12T и 13T - по отдельности?
|
|
67
|
+
# COMPLETED, PENDING, TRADING, BUYER_PAYED, DISTRIBUTING, COMPLETED, IN_APPEAL, CANCELLED, CANCELLED_BY_SYSTEM
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class OrderErr(IntEnum):
|
|
71
|
+
ok = 0
|
|
72
|
+
i_wait_for_release = 1
|
|
73
|
+
payments_exists_on_cancel = 2
|
|
74
|
+
taker_balance_deficit = 3
|
|
75
|
+
# negative results is for agent
|
|
76
|
+
maker_balance_deficit = -4
|
|
77
|
+
uncompleted_orders = 5
|
|
78
|
+
wrong_status_for_hot = -6
|
|
79
|
+
cant_cancel = 7
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class OrderAction(IntEnum):
|
|
83
|
+
# requested
|
|
84
|
+
taker_create = 1
|
|
85
|
+
wait_for_cancel = 0
|
|
86
|
+
# created
|
|
87
|
+
buyer_pay = 2
|
|
88
|
+
seller_confirm = 3
|
|
89
|
+
buyer_cancel = 4
|
|
90
|
+
# paid
|
|
91
|
+
wait_for_pay = 5
|
|
92
|
+
seller_appeal = 6
|
|
93
|
+
buyer_appeal = 7
|
|
94
|
+
# appealed by seller
|
|
95
|
+
buyer_dispute_appeal_s = 8
|
|
96
|
+
buyer_agree_appeal_s = 10 # cancel
|
|
97
|
+
wait_appeal_s = 12 # -> cancel
|
|
98
|
+
# appealed by buyer
|
|
99
|
+
seller_dispute_appeal_b = 9
|
|
100
|
+
seller_agree_appeal_b = 11 # confirm
|
|
101
|
+
wait_appeal_b = 13 # -> confirm
|
|
102
|
+
wait_disputed_appeal = 14 # ?
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class CoinType(IntEnum):
|
|
106
|
+
normal = 1
|
|
107
|
+
game = 2
|
|
108
|
+
corp = 3
|
|
109
|
+
stock = 4
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class ExType(IntEnum):
|
|
113
|
+
p2p = 1
|
|
114
|
+
cex = 2
|
|
115
|
+
main = 3 # p2p+cex
|
|
116
|
+
dex = 4
|
|
117
|
+
tg = 5
|
|
118
|
+
futures = 8
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class DepType(IntEnum):
|
|
122
|
+
earn = 1
|
|
123
|
+
stake = 2
|
|
124
|
+
beth = 3
|
|
125
|
+
lend = 4
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class AddrExType(IntEnum):
|
|
129
|
+
spot = 1
|
|
130
|
+
earn = 2
|
|
131
|
+
found = 3
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class TradeType(IntEnum):
|
|
135
|
+
BUY = 0
|
|
136
|
+
SELL = 1
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class PmType(IntEnum):
|
|
140
|
+
common = 0
|
|
141
|
+
bank_acc = 1 # no. or IBAN
|
|
142
|
+
emoney = 2 # QR / phone-based
|
|
143
|
+
cash = 3 # ваучеры / агентские
|
|
144
|
+
card = 4 # fintech/processing
|
|
145
|
+
local = 5 # региональные: bank_routing-based: IFSC(Индия), CLABE(Мексика), банк.коды ЛатАм
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class TaskType(IntEnum):
|
|
149
|
+
invite_approve = 1
|
|
150
|
+
order_user_define = 2
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class FileType(IntEnum):
|
|
154
|
+
pdf = 1
|
|
155
|
+
jpg = 2
|
|
156
|
+
png = 3
|
|
157
|
+
webp = 4
|
|
158
|
+
mov = 5
|
|
159
|
+
mp4 = 6
|
|
160
|
+
gif = 7
|
|
161
|
+
svg = 8
|
|
162
|
+
tgs = 9
|
|
163
|
+
jpeg = 10
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
class AgentStatus(IntEnum):
|
|
167
|
+
off = 0
|
|
168
|
+
race = 1
|
|
169
|
+
listen = 2
|
|
170
|
+
race_listen = 3
|
|
171
|
+
# ... = 4
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
class SynonymType(IntEnum):
|
|
175
|
+
name = 1
|
|
176
|
+
ppo = 2
|
|
177
|
+
from_party = 3
|
|
178
|
+
to_party = 4
|
|
179
|
+
slip_req = 5
|
|
180
|
+
slip_send = 6
|
|
181
|
+
abuser = 7
|
|
182
|
+
scale = 8
|
|
183
|
+
slavic = 9
|
|
184
|
+
mtl_like = 10
|
|
185
|
+
bank = 11
|
|
186
|
+
bank_side = 12
|
|
187
|
+
sbp_strict = 13
|
|
188
|
+
contact = 14
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
class Boundary(IntEnum):
|
|
192
|
+
no = 0
|
|
193
|
+
left_word = 1
|
|
194
|
+
right_word = 2
|
|
195
|
+
both_word = 3
|
|
196
|
+
left_all = 4
|
|
197
|
+
right_all = 5
|
|
198
|
+
both_all = 6
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
class SbpStrict(IntEnum):
|
|
202
|
+
no = 0
|
|
203
|
+
sbp = 1
|
|
204
|
+
card = 2
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
class Party(IntEnum):
|
|
208
|
+
fst = 0
|
|
209
|
+
fam = 1
|
|
210
|
+
lk = 2 # lk-photo/video/comment
|
|
211
|
+
trd = 3
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
class Slip(IntEnum):
|
|
215
|
+
no = 0
|
|
216
|
+
screen = 1
|
|
217
|
+
pdf = 2
|
|
218
|
+
pdf_mail = 3
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
class NameType(IntEnum):
|
|
222
|
+
no_slavic = 0
|
|
223
|
+
slavic = 1
|
|
224
|
+
fake = 2
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
class AbuserType(IntEnum):
|
|
228
|
+
no = 0
|
|
229
|
+
rating = 1 # рейтинг: жмет "Оплачено" сразу, "Отмена" по апелляции
|
|
230
|
+
fake = 2 # реклама
|
|
231
|
+
cash = 3 # типа кэш обменник, но хз
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class ExStatus(IntEnum):
|
|
235
|
+
plan = 0
|
|
236
|
+
parted = 1
|
|
237
|
+
full = 2
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
class ExAction(IntEnum):
|
|
241
|
+
"""Order"""
|
|
242
|
+
|
|
243
|
+
get_orders = 0 # Получение заявок за заданное время, в статусе, по валюте, монете, направлению: `get_orders(status=OrderStatus.active, coin='USDT', cur='RUB', is_sell=False) => [order]`
|
|
244
|
+
order_request = 1 # [T] Запрос на старт сделки
|
|
245
|
+
order_request_ask = -1 # [M] - Запрос мейкеру на сделку
|
|
246
|
+
cancel_request = 2 # [T] Отмена запроса на сделку
|
|
247
|
+
request_canceled = -2 # [M] - Уведомление об отмене запроса на сделку
|
|
248
|
+
accept_request = 3 # [M] Одобрить запрос на сделку
|
|
249
|
+
request_accepted = -3 # [T] Уведомление об одобрении запроса на сделку
|
|
250
|
+
reject_request = 4 # [M] Отклонить запрос на сделку
|
|
251
|
+
request_rejected = -4 # [T] Уведомление об отклонении запроса на сделку
|
|
252
|
+
mark_payed = 5 # [B] Перевод сделки в состояние "оплачено", с отправкой чека
|
|
253
|
+
payed = -5 # [S] Уведомление продавца об оплате
|
|
254
|
+
cancel_order = 6 # [B] Отмена сделки
|
|
255
|
+
order_canceled = -6 # [S] Уведомление продавцу об отмене ордера покупателем
|
|
256
|
+
confirm = 7 # [S] Подтвердить получение оплаты
|
|
257
|
+
order_completed = -7 # [B] Уведомление покупателю об успешном завершении продавцом
|
|
258
|
+
appeal_available = -8 # [S, B] Уведомление о наступлении возможности подать апелляцию
|
|
259
|
+
start_appeal = 9 # , 10 # [S, B] Подать апелляцию со скриншотом/видео/файлом
|
|
260
|
+
appeal_started = -9 # , -10 # [S, B] Уведомление о поданной на меня апелляции
|
|
261
|
+
dispute_appeal = 11 # , 12 # [S, B] Встречное оспаривание полученной апелляции со скриншотом/видео/файлом
|
|
262
|
+
appeal_disputed = -11 # , -12 # [S, B] Уведомление о встречном оспаривание поданной апелляции
|
|
263
|
+
order_completed_by_appeal = -13 # [S, B] Уведомление о завершении сделки по апелляции
|
|
264
|
+
order_canceled_by_appeal = -14 # [B, S] Уведомление об отмене сделки по апелляции
|
|
265
|
+
cancel_appeal = 15 # [B, S] Отмена апелляции
|
|
266
|
+
appeal_canceled = -15 # [B, S] Уведомление об отмене апелляции против меня
|
|
267
|
+
send_order_msg = 16 # Отправка сообщения юзеру в чат по ордеру с приложенным файлом
|
|
268
|
+
got_order_msg = -16 # Получение сообщения в чате по ордеру
|
|
269
|
+
send_appeal_msg = 17 # Отправка сообщения по апелляции
|
|
270
|
+
got_appeal_msg = -17 # Получение сообщения по апелляции
|
|
271
|
+
""" Ex: Public """
|
|
272
|
+
# curs = 19 # Список поддерживаемых валют тейкера
|
|
273
|
+
pms = 20 # Список платежных методов по каждой валюте
|
|
274
|
+
cur_pms_map = 21 # Мэппинг валюта => платежные методы
|
|
275
|
+
coins = 22 # Список торгуемых монет (с ограничениями по валютам, если есть)
|
|
276
|
+
pairs = 23 # Список пар валюта/монет
|
|
277
|
+
ads = 24 # Список объяв по покупке/продаже, валюте, монете, платежному методу (buy/sell, cur, coin, pm)
|
|
278
|
+
set_coins = 44 # обновление монет биржи в бд
|
|
279
|
+
set_curs = 19 # обновление валют и платежек биржи в бд
|
|
280
|
+
set_pms = 45 # обновление валют и платежек биржи в бд
|
|
281
|
+
set_pairs = 46 # обновление пар биржи в бд
|
|
282
|
+
ad = 42 # Чужая объява по id
|
|
283
|
+
""" Agent: Fiat """
|
|
284
|
+
my_creds = 25 # Список реквизитов моих платежных методов
|
|
285
|
+
cred_new = 26 # Создание реквизита моего платежного метода
|
|
286
|
+
cred_upd = 27 # Редактирование реквизита моего платежного метода
|
|
287
|
+
cred_del = 28 # Удаление реквизита моего платежного метода
|
|
288
|
+
""" Agent: Ad """
|
|
289
|
+
my_ads = 29 # Список моих объявлений
|
|
290
|
+
my_ad = 43 # Моя объява по id
|
|
291
|
+
ad_new = 30 # Создание объявления
|
|
292
|
+
ad_upd = 31 # Редактирование объявления
|
|
293
|
+
ad_del = 32 # Удаление объявления
|
|
294
|
+
ad_switch = 33 # Вкл/выкл объявления
|
|
295
|
+
ads_switch = 34 # Вкл/выкл всех объявлений
|
|
296
|
+
""" Agent: Taker """
|
|
297
|
+
get_user = 35 # Получить объект юзера по его id
|
|
298
|
+
send_user_msg = 36 # Отправка сообщения юзеру с приложенным файлом
|
|
299
|
+
block_user = 37 # [Раз]Блокировать пользователя
|
|
300
|
+
rate_user = 38 # Поставить отзыв пользователю
|
|
301
|
+
""" Agent: Inbound """
|
|
302
|
+
got_user_msg = -36 # Получение сообщения от пользователя
|
|
303
|
+
got_blocked = -37 # Получение уведомления о [раз]блокировке пользователем
|
|
304
|
+
got_rated = -38 # Получение уведомления о полученном отзыве
|
|
305
|
+
|
|
306
|
+
""" Assets """
|
|
307
|
+
assets = 39 # Балансы моих монет
|
|
308
|
+
deposit = 40 # Получить реквизиты для депозита монеты
|
|
309
|
+
deposited = -40 # Получена монета
|
|
310
|
+
withdraw = 41 # Вывести монету
|
|
311
|
+
withdrew = -41 # Монета выведена
|
xync_db/exceptions.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from enum import IntEnum
|
|
2
|
+
from json import loads
|
|
3
|
+
|
|
4
|
+
from asyncpg.exceptions import RaiseError
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ExcType(IntEnum):
|
|
8
|
+
InsufficientBalance = 1
|
|
9
|
+
TxIdPackMismatch = 2
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class PgRaiseError(ValueError):
|
|
13
|
+
typ: ExcType
|
|
14
|
+
|
|
15
|
+
def __init__(self, e: RaiseError) -> None:
|
|
16
|
+
typ, msg = e.args[0].split(": ")
|
|
17
|
+
self.typ = ExcType[typ]
|
|
18
|
+
super().__init__(typ, loads(msg))
|
xync_db/graph.py
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from xync_db.enums import OrderAction, OrderStatus
|
|
2
|
+
|
|
3
|
+
acts = (
|
|
4
|
+
{ # buyer
|
|
5
|
+
# 1
|
|
6
|
+
OrderStatus.created: {
|
|
7
|
+
OrderAction.buyer_cancel: OrderStatus.canceled,
|
|
8
|
+
OrderAction.buyer_pay: OrderStatus.paid,
|
|
9
|
+
},
|
|
10
|
+
# 2
|
|
11
|
+
OrderStatus.paid: {
|
|
12
|
+
OrderAction.buyer_cancel: OrderStatus.canceled,
|
|
13
|
+
OrderAction.buyer_appeal: OrderStatus.appealed_by_buyer,
|
|
14
|
+
},
|
|
15
|
+
# 5
|
|
16
|
+
OrderStatus.appealed_by_seller: {
|
|
17
|
+
OrderAction.buyer_cancel: OrderStatus.canceled,
|
|
18
|
+
OrderAction.buyer_dispute_appeal_s: OrderStatus.appeal_disputed,
|
|
19
|
+
},
|
|
20
|
+
# 6
|
|
21
|
+
OrderStatus.appealed_by_buyer: {
|
|
22
|
+
OrderAction.buyer_cancel: OrderStatus.canceled,
|
|
23
|
+
},
|
|
24
|
+
# 7
|
|
25
|
+
OrderStatus.appeal_disputed: {
|
|
26
|
+
OrderAction.buyer_cancel: OrderStatus.canceled,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
{ # seller
|
|
30
|
+
# 2
|
|
31
|
+
OrderStatus.paid: {
|
|
32
|
+
OrderAction.seller_confirm: OrderStatus.completed,
|
|
33
|
+
OrderAction.seller_appeal: OrderStatus.appealed_by_seller,
|
|
34
|
+
},
|
|
35
|
+
# 5
|
|
36
|
+
OrderStatus.appealed_by_seller: {
|
|
37
|
+
OrderAction.seller_confirm: OrderStatus.completed,
|
|
38
|
+
},
|
|
39
|
+
# 6
|
|
40
|
+
OrderStatus.appealed_by_buyer: {
|
|
41
|
+
OrderAction.seller_dispute_appeal_b: OrderStatus.appeal_disputed,
|
|
42
|
+
OrderAction.seller_confirm: OrderStatus.completed,
|
|
43
|
+
},
|
|
44
|
+
# 7
|
|
45
|
+
OrderStatus.appeal_disputed: {
|
|
46
|
+
OrderAction.seller_confirm: OrderStatus.completed,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
waits: dict[OrderStatus, dict[OrderAction, OrderStatus]] = {
|
|
53
|
+
# 1
|
|
54
|
+
OrderStatus.created: {
|
|
55
|
+
OrderAction.wait_for_cancel: OrderStatus.canceled,
|
|
56
|
+
},
|
|
57
|
+
# 5
|
|
58
|
+
OrderStatus.appealed_by_seller: {
|
|
59
|
+
OrderAction.wait_appeal_s: OrderStatus.canceled,
|
|
60
|
+
},
|
|
61
|
+
# 6
|
|
62
|
+
OrderStatus.appealed_by_buyer: {
|
|
63
|
+
OrderAction.wait_appeal_b: OrderStatus.completed,
|
|
64
|
+
},
|
|
65
|
+
}
|
xync_db/logo.png
ADDED
|
Binary file
|
xync_db/models/CLAUDE.md
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
All Tortoise ORM models (~60) are defined in `__init__.py`. Models are organized into domain groups listed below.
|
|
8
|
+
|
|
9
|
+
## Base Classes
|
|
10
|
+
|
|
11
|
+
- **`Model`** (from `x_auth.models`) — primary base with `_name`, `_icon`, `PydanticMeta` support
|
|
12
|
+
- **`BaseModel`** (tortoise) — used for through-tables (`CurEx`, `CoinEx`, `PmEx`, `PmExBank`) that don't need full model features
|
|
13
|
+
- **`TgUser`** (from `x_auth.models`) — Telegram user base, extended by `User`
|
|
14
|
+
- **`TsTrait`** (from `x_model.models`) — mixin adding auto `created_at`/`updated_at`
|
|
15
|
+
|
|
16
|
+
Re-exported models from `x_auth`: `Username`, `Proxy`, `Dc`, `Fcm`, `App`, `Session`, `Peer`, `UpdateState`, `Version`, `Country` (as `BaseCountry`).
|
|
17
|
+
|
|
18
|
+
## Field Conventions
|
|
19
|
+
|
|
20
|
+
- **UInt fields**: `UInt1Field` (1 byte), `UInt2Field` (2), `UInt4Field` (4), `UInt8Field` (8) — custom unsigned integers from `x_model.field`
|
|
21
|
+
- **Monetary integers**: amounts stored as `int / 10^scale` where `scale` comes from the related `Cur` or `Coin`
|
|
22
|
+
- **Percentages**: stored as `/10_000` (basis points) — fields: `premium`, `fee`, `apr`
|
|
23
|
+
- **Binary**: `BinaryField` for keys/proofs, `UniqBinaryField` for unique binary (e.g., `File.ref`)
|
|
24
|
+
- **Timestamps**: `DatetimeSecField` for second-precision datetimes (`shared_at`, `payed_at`, etc.)
|
|
25
|
+
- **FK convention**: all `ForeignKeyField` / `OneToOneField` use `on_update=CASCADE`
|
|
26
|
+
- **Composite uniqueness**: via `Meta.unique_together`, commonly `(ex_id, exid)` for exchange-mapped entities
|
|
27
|
+
|
|
28
|
+
## Model Attributes
|
|
29
|
+
|
|
30
|
+
- **`_name`**: set of field paths for string representation (supports `__` traversal, e.g. `"pair_side__pairex__coin__ticker"`)
|
|
31
|
+
- **`_icon`**: UI icon identifier (e.g. `"ad"`, `"seeding"`, `"file"`)
|
|
32
|
+
- **`repr()`**: human-readable formatting on select models (`Cred`, `Dep`, `Investment`, `ExStat`, `Vpn`, `Invite`, `Credit`)
|
|
33
|
+
|
|
34
|
+
## Domain Groups
|
|
35
|
+
|
|
36
|
+
### Currency & Exchange
|
|
37
|
+
`Cur` -> `CurEx` <- `Ex`, `Coin` -> `CoinEx` <- `Ex`, `Net`, `Pair` -> `PairSide` -> `PairEx`
|
|
38
|
+
|
|
39
|
+
- `Cur.id` = `UInt1Field` (max 255 fiat currencies)
|
|
40
|
+
- `Coin.id` = `SmallIntField`
|
|
41
|
+
- `Ex.id` = `UInt1Field` (max 255 exchanges)
|
|
42
|
+
- Through-tables (`CurEx`, `CoinEx`) carry `exid` (exchange's internal ID string) and exchange-specific `scale`/`minimum`
|
|
43
|
+
|
|
44
|
+
### Users & Auth
|
|
45
|
+
`Person` -> `User` (extends `TgUser`), `Actor` -> `Agent`
|
|
46
|
+
|
|
47
|
+
- `Person` groups actors/credentials under a human identity; `status` via `PersonStatus`
|
|
48
|
+
- `User` holds Ed25519 keypair (`prv`/`pub` as raw bytes) for signing `Transaction`s
|
|
49
|
+
- `Actor` = exchange account `(ex_id, exid)` unique; links to `Person`
|
|
50
|
+
- `Agent` = authenticated session (one-to-one with `Actor`); holds `auth` JSON blob + expiry
|
|
51
|
+
- `Addr` = crypto deposit address `(coin_id, actor_id)` unique; linked to `Net`s via `NetAddr`
|
|
52
|
+
- `Asset` = balance snapshot `(addr_id, agent_id, typ)` unique; amounts `free`/`freeze`/`lock`/`target`
|
|
53
|
+
|
|
54
|
+
actor.set_user(username_id):
|
|
55
|
+
При создании юзера(User) в sql-триггере автоматически создается персона(Person) с его user_id.
|
|
56
|
+
А при создании актора(Actor) создается персона без user_id, но в actor.person_id = id этой персоны.
|
|
57
|
+
И когда юзер заходит в объявление одного из агентов(Agent) первый раз, создается его актор для биржи (на которой
|
|
58
|
+
размещено это объявление) и новая персона этого актора.
|
|
59
|
+
Если к персоне юзера еще не "привязано" ни одного актора, 2 персоны для юзера с одним актором избыточны, их нужно
|
|
60
|
+
смерджить: т.е старой персоне юзера назначить имя, креды(creds) и актора этой новой персоны, а новую "осиротевшую"
|
|
61
|
+
персону удалить.
|
|
62
|
+
Далее, если этот же юзер будет заходить с других акторов:
|
|
63
|
+
- других бирж, но с тем же именем: это та же персона нужно так же смерджить новую персону нового актора с существующей.
|
|
64
|
+
- с другим именем: значит это уже другая персона, и существующая персона(ы) уже "занята" существующим(и) актором(ами),
|
|
65
|
+
тогда уже не надо мержить новую персону нового актора, оставляем новую.
|
|
66
|
+
|
|
67
|
+
### Payment Methods
|
|
68
|
+
`PmGroup` -> `Pm` -> `PmCur` <- `Cur`, `PmEx` <- `Ex`, `PmExBank`
|
|
69
|
+
|
|
70
|
+
- `Pm.norm` — normalized name (used in dynamic client path: `xync_client.Pms.{norm}.agent`)
|
|
71
|
+
- `Cred` = user's payment credential `(person_id, pmcur_id, ovr_pm_id)` unique
|
|
72
|
+
- `CredEx` = credential registered on exchange `(ex_id, exid)` unique
|
|
73
|
+
- `Fiat` = balance tracker (one-to-one with `Cred`): `amount`, `target`, `min_deposit`
|
|
74
|
+
- `PmAgent` = automation account for a PM `(pm_id, user_id)` unique
|
|
75
|
+
|
|
76
|
+
### P2P Trading
|
|
77
|
+
`Ad` -> `MyAd` -> `Race` -> `RaceStat`, `Order` -> `Msg`/`Transfer`/`Task`, `Hot`
|
|
78
|
+
|
|
79
|
+
- `Ad` = exchange advertisement `(exid, maker_id)` unique; carries `price`, `premium`, `amount`, `min_fiat`/`max_fiat`, `status` (`AdStatus`), optional `Cond`
|
|
80
|
+
- `MyAd` = our managed ad (one-to-one with `Ad`); adds race tracking, share URLs, linked `CredEx`s
|
|
81
|
+
- `Order` = P2P trade `(exid)` unique; references `Ad`, `Cred`, taker/maker `Actor`s; `status` via `OrderStatus`
|
|
82
|
+
- `Hot` = warm-up trading session; many-to-many with `Actor`s and `Order`s
|
|
83
|
+
- `Msg` = order chat message with optional `File` attachment
|
|
84
|
+
- `Transfer` = order payment record with `amount`, optional `File` (receipt)
|
|
85
|
+
|
|
86
|
+
### Conditions (Ad parsing)
|
|
87
|
+
`Cond` -> `CondParsed`, `Synonym`, `CondSim`
|
|
88
|
+
|
|
89
|
+
- `Cond.raw_txt` = original ad conditions text (4095 chars max, unique)
|
|
90
|
+
- `CondParsed` = structured parse result: `to_party`/`from_party` (`Party`), `ppo`, `slip_req`/`slip_send` (`Slip`), abuse flags, linked bank `Pm`s
|
|
91
|
+
- `Synonym` = condition term with `typ` (`SynonymType`), optional regex (`is_re`), boundary matching
|
|
92
|
+
|
|
93
|
+
### Transactions (XyncPay)
|
|
94
|
+
`Transaction`, `Sign`
|
|
95
|
+
|
|
96
|
+
- `Transaction.id` = deterministic UUID packed from: `type(2bit) + ts(30bit) + cur_id(1byte) + receiver_id(3bytes) + amount(5bytes) + sender_id(3bytes)` = 16 bytes
|
|
97
|
+
- `Transaction.proof` = 128 bytes (64 sender signature + 64 validator signature), Ed25519
|
|
98
|
+
- `Transaction.status` progresses: `request` -> `signed` -> `verified`
|
|
99
|
+
- Key methods: `pack` (property), `sign(front_sign)`, `approve(prv)`, `check(vld_pub)`, `snapshot(ts)` (raw SQL)
|
|
100
|
+
- DB-level PL/pgSQL triggers enforce: balance checks on insert, immutability on update, no deletes
|
|
101
|
+
|
|
102
|
+
### Financial Products
|
|
103
|
+
`Dep` -> `Investment`, `TopUpAble` -> `TopUp`
|
|
104
|
+
|
|
105
|
+
### Management
|
|
106
|
+
`Limit`, `ExStat`, `Vpn`, `Invite`, `Credit`, `File`
|
|
107
|
+
|
|
108
|
+
## Dynamic Client Loading
|
|
109
|
+
|
|
110
|
+
Models delegate exchange-specific logic to `xync_client` via runtime imports:
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
Ex.client() -> xync_client.{ex.name}.ex.ExClient
|
|
114
|
+
Agent.client() -> xync_client.{ex.name}.agent.AgentClient
|
|
115
|
+
Actor.asset_client() -> xync_client.{ex.name}.asset.AssetClient
|
|
116
|
+
Order.client() -> xync_client.{ex.name}.order.OrderClient
|
|
117
|
+
Pm.client() -> xync_client.Pms.{pm.norm}
|
|
118
|
+
PmAgent.client() -> xync_client.Pms.{pm.norm}.agent
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Enums
|
|
122
|
+
|
|
123
|
+
All enums are in `xync_db/enums.py` (all `IntEnum`). Key ones: `AdStatus`, `OrderStatus`, `OrderAction`, `OrderErr`, `ExType`, `ExStatus`, `ExAction` (~50 actions), `PmType`, `TransactionStatus`, `PersonStatus`, `UserStatus`, `HotStatus`, `FileType`, `DepType`, `AgentStatus`.
|
|
124
|
+
|
|
125
|
+
`TransactionStatus` is imported as `TS` alias in this file.
|