8.0 KiB
FLOW.md — как ходят данные: кто, кому и в какой момент (sequence-диаграммы)
Репо: pump-game-ops (мета-репо, документация). Статус: живой, дополняется.
Цель — раз и навсегда зафиксировать порядок обмена сообщениями между участниками (фронт, бэкенд/релейер, контракт, RFС Solana, кошелёк, pump.fun), чтобы было понятно «кто кому что шлёт и в какой момент», включая тонкость согласия игрока (подписи).
Легенда участников:
- Клиент (браузер / Unity WebGL) — UI игрока.
- Phantom — браузерный кошелёк (держит приватный ключ игрока; согласие = подпись).
- Бэкенд (релейер) — наш сервер: строит/ретраслит ставки, держит ваулт-фандинг.
- Контракт —
smart-updown-tokenна цепочке Solana (ваулт фантиков, create/close bet). - RPC Solana — узел цепочки (localnet
192.168.76.199:8890, на бою — публичный). - pump.fun — меняльная лавка (на бою; SOL↔фантики по живому курсу).
1. КАК ЭТО РАБОТАЕТ СЕЙЧАС (localnet, тестовый пульт, БЕЗ pump.fun и без Phantom)
Текущее состояние (см.
test-front,smart-updown-token/relayer). Ставка подписывается сервером (custodial-кошелёк шлюза), кошелёк игрока в подписи НЕ участвует. Фантики и SOL накинуты вручную (тест), обменника нет.
sequenceDiagram
participant U as Игрок (браузер)
participant F as Пульт (test-front)
participant G as HTTP-шлюз gateway.ts
participant S as Контракт (localnet)
participant R as RPC Solana (8890)
U->>F: открыть страницу, «Обновить state»
F->>G: GET /state
G->>S: readGlobal()
S-->>G: min/max/expiry/vault/counter
G-->>F: JSON (лимиты, vault)
F-->>U: показать лимиты/ваулт
U->>F: «Проверить баланс» (адрес)
F->>G: GET /balance/{address}
G->>R: getBalance, getTokenAccountBalance (ATA)
R-->>G: SOL + фантики
G-->>F: {sol, tokenHuman}
F-->>U: «Фантики: N, SOL: M»
U->>F: «Сделать ставку» (сумма, сторона)
F->>G: POST /bet {side, amountUnits, address?}
G->>S: createBet (подпись КЛЮЧОМ ШЛЮЗА)
S-->>G: tx (в сеть)
G-->>F: {id, bettor, tx}
F-->>U: «Ставка id=X ушла»
Note over U,G: пауза ~15с (expiry) — контракт не даёт закрыть раньше
U->>F: «Закрыть ставку» (id)
F->>G: POST /close {id}
G->>S: closeBet (по текущей цене, подпись шлюза)
S-->>G: исход (payout_done / house_won)
G-->>F: {statusName, exitPrice}
F-->>U: «выиграл» / «дом выиграл»
Кто подписывает согласие игрока? В этом режиме — никто из игрока. Согласие даётся нажатием кнопки в пульте; подписывает сервер (custodial-ключ шлюза). Настоящего вывода/пополнения нет — балансы накинуты.
2. КАК ЭТО ДОЛЖНО РАБОТАТЬ ПО-НАСТОЯЩЕМУ (боевой, pump.fun + Phantom + подпись игрока)
Целевая архитектура (фазы devnet→mainnet). Здесь согласие игрока = подпись в Phantom, а обмен делается через pump.fun по живому курсу.
sequenceDiagram
participant U as Игрок
participant F as Фронт (Unity/WebGL)
participant P as Phantom (кошелёк)
participant B as Бэкенд (релейер)
participant S as Контракт (фантики)
participant R as RPC Solana
participant PF as pump.fun (лавка)
%% --- ПОПОЛНЕНИЕ: SOL -> фантики ---
U->>F: «Пополнить» (SOL)
F->>P: запросить подпись swap (акис consent)
P-->>U: «Согласен(на) на обмен?»
U-->>P: ОК
P-->>F: подписанная swap-транзакция
F->>B: POST /api/pump/swap (подпись)
B->>PF: swap SOL→фантики (живой курс)
PF->>R: обработать swap
R-->>B: фантики на ATA игрока
B-->>F: ok
F-->>U: «Баланс +N фантиков»
%% --- СТАВКА ---
U->>F: «Поставить» (сумма, сторона)
F->>P: построить createBet, запросить подпись
P-->>U: «Подтвердить ставку?»
U-->>P: ОК (согласие)
P-->>F: подписанная createBet
F->>B: POST /api/bet (ретрансляция)
B->>R: sendRawTransaction (ваулт→контракт)
R-->>B: tx принята
B-->>F: {id, status}
F-->>U: «Ставка ушла, ждём исход»
%% --- ВЫВОД: фантики -> SOL ---
U->>F: «Вывести» (фантики)
F->>P: запросить подпись swap
P-->>U: «Согласен(на) на обмен?»
U-->>P: ОК
P-->>F: подписанный swap
F->>B: POST /api/pump/swap (обратный)
B->>PF: swap фантики→SOL (живой курс)
PF->>R: обработать
R-->>B: SOL на кошелёк игрока
B-->>F: ok
F-->>U: «Баланс -N фантиков, +SOL»
Главное отличие от текущего: в бою согласие игрока — это криптографическая подпись в Phantom на каждое действие с деньгами (пополнение, ставка, вывод). Сервер никогда не видит приватный ключ игрока — только подписанную транзакцию, которую ретранслирует в сеть. Пульт без Phantom (раздел 1) — только для гонки механики на localnet.
3. Сравнение «сейчас» vs «боевой»
| Аспект | Сейчас (localnet) | Боевой (devnet→mainnet) |
|---|---|---|
| Согласие игрока | кнопка пульта | подпись в Phantom |
| Кто подписывает ставку | сервер (custodial ключ шлюза) | игрок (Phantom) |
| Пополнение/вывод | нет (балансы накинуты) | swap через pump.fun по живому курсу |
| Сеть | localnet (192.168.76.199:8890) | devnet→mainnet (реальная Solana) |
| Валюта | тестовые фантики (накинуты) | REAL фантики за реальный SOL |
| Приватный ключ | на сервере (custodial) | только в Phantom игрока |
4. Опорные репозитории/файлы
- Пульт без Phantom:
subochev/test-front→index.html(дёргает шлюз по/api/...). - HTTP-шлюз:
subochev/smart-updown-token→relayer/src/gateway.ts(/state,/balance/{address},/bet,/close,/faucet/{address}— последний только localnet). - Релейер (серверный казначей): там же →
relayer/. - Бэкенд-свап-клиент pump.fun:
subochev/smart-updown-server→src/main/kotlin/.../PumpApiClient.kt,PumpApiController.kt(/api/pump/swap). - Публика:
deploy/flows(этот файл).