From ba14806e6ca35813118462978b826e8e21564fa8 Mon Sep 17 00:00:00 2001 From: Caffeine Date: Thu, 10 Sep 2026 05:57:26 +0300 Subject: [PATCH] =?UTF-8?q?docs:=20FLOW.md=20=E2=80=94=20sequence-=D0=B4?= =?UTF-8?q?=D0=B8=D0=B0=D0=B3=D1=80=D0=B0=D0=BC=D0=BC=D1=8B=20(UML)=20?= =?UTF-8?q?=D0=BA=D0=B0=D0=BA=20=D1=85=D0=BE=D0=B4=D1=8F=D1=82=20=D0=B4?= =?UTF-8?q?=D0=B0=D0=BD=D0=BD=D1=8B=D0=B5:=20=D1=81=D0=B5=D0=B9=D1=87?= =?UTF-8?q?=D0=B0=D1=81=20(localnet+=D1=88=D0=BB=D1=8E=D0=B7,=20=D0=B1?= =?UTF-8?q?=D0=B5=D0=B7=20Phantom)=20=D0=B8=20=D0=B1=D0=BE=D0=B5=D0=B2?= =?UTF-8?q?=D0=BE=D0=B9=20(pump.fun+Phantom+=D0=BF=D0=BE=D0=B4=D0=BF=D0=B8?= =?UTF-8?q?=D1=81=D1=8C=20=D0=B8=D0=B3=D1=80=D0=BE=D0=BA=D0=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 ++ docs/FLOW.md | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 docs/FLOW.md diff --git a/README.md b/README.md index 9c2736c..0562d08 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,9 @@ - **decimals = 6**, токен через **Token-2022** (по доке pump.fun `create_v2`). - Ставки идут **фантиками через контракт** → контракт переводить с SOL на SPL-токен (это ядро). +Как ходят данные (кто кому что шлёт, включая согласие/подпись игрока) — `docs/FLOW.md` +(sequence-диаграммы: текущий localnet-режим без Phantom и целевой боевой с pump.fun+Phantom). + ## Статус проекта (сводка) Задачи и статусы — в `TASKS.md` (или `docs/TASKS.md`). Здесь — только верхи: diff --git a/docs/FLOW.md b/docs/FLOW.md new file mode 100644 index 0000000..9afd802 --- /dev/null +++ b/docs/FLOW.md @@ -0,0 +1,150 @@ +# 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 **накинуты вручную** (тест), обменника нет. + +```mermaid +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** по живому курсу. + +```mermaid +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` (этот файл). \ No newline at end of file