docs: привести README и API.md в соответствие с живым стендом

Оба файла описывали состояние, которого больше нет, и содержали ошибки,
из-за которых внешний разработчик не собрал бы рабочий фронт:

- README описывал Phantom, swap ввод/вывод (POST /api/pump/swap), STUB-ключи
  и Фазу 1 — ничего этого в index.html нет. Указан нерабочий API base
  (smart-updown.binom.pw вместо testfront.binom.pw) и адрес контракта FMM….
  «Ставка через поллинг» — поллинга нет, события по WS.
- API.md держал раздел «часть ставок зависает без исхода» со статусом
  «не исправлено» — баг закрыт 14.09.2026 в контракте. По этой доке писали бы
  обходной код под проблему, которой нет.

README переписан под фактический index.html: HTTP-шлюз без Phantom,
сценарий кошелёк→фаусет→ставка→WS-исход, три исхода, правило 409.
Секция API.md заменена на «Ничья при exitPrice == entryPrice» (штатный
исход, доля ~трети), историческая сноска на SEC-9 сохранена.

Проверено: полный сценарий снаружи по новой доке проходит
(кошелёк → фаусет 10000 → ставка id=44 → исход по балансу).
This commit is contained in:
Caffeine
2026-09-14 02:24:53 +03:00
parent 30a17f7d99
commit b8c040dedc
2 changed files with 41 additions and 48 deletions
+10 -17
View File
@@ -144,27 +144,20 @@ await fetch(`${BASE}/bet`, {
--- ---
## ⚠️ Известная проблема: часть ставок зависает без исхода ## Ничья при `exitPrice == entryPrice`
**Симптом:** пришло `bet_open`, а `bet_closed` не приходит вообще; повторная ставка с того же Если цена на момент экспирации в точности равна цене входа, ставка **не зависает**:
адреса вечно отвечает `409`. контракт возвращает игроку **ровно сумму ставки без множителя**, ставка переходит в
статус `3`, по WS уходит `bet_closed` со `statusName: "refunded"`.
**Причина:** если цена на момент экспирации в точности равна цене входа, контракт Доля таких окон — около **трети** ставок (замер 33.6 % на 34 769 окнах). Это **нормальный
(`close_bet.rs:66`) молча выходит `return Ok(())` — статус остаётся `open`, ставка не штатный исход**, а не ошибка: клиенту надо просто показать третий вид результата.
финализируется. А поскольку цена выхода берётся по **фиксированному** моменту экспирации,
повторные попытки планировщика получают ту же самую пару значений — и цикл не заканчивается
никогда (лог: `settle: #N still open (exit==entry at …), will retry`).
**Масштаб (замер на 580 минутах живой истории, 34 769 окон):** **33.6 %** ставок попадают в Рекомендация фронту: обрабатывать **три** исхода `bet_closed` (`payout_done` / `house_won`
равные цены — **примерно каждая третья**. / `refunded`) и не показывать `refunded` как проигрыш.
**Что это значит для фронта:** каждая третья ставка не завершится, а игрок потеряет > Исторически (до 14.09.2026) такие ставки зависали навсегда; разбор —
возможность играть с этого адреса (правило «одна открытая ставка» + `409`). > `pump-game-ops/docs/SECURITY.md`, пункт `SEC-9`.
**Обходите:** для каждого игрока используйте новый адрес на ставку, либо показывайте
«ставка в ожидании».
**Статус:** не исправлено, ждёт решения владельца (политика ничьей / закрытие соседней ценой
из истории). Подробности — `pump-game-ops/docs/SECURITY.md`, пункт **SEC-9**.
--- ---
+31 -31
View File
@@ -1,46 +1,46 @@
# test-front — технический тестовый фронт (Binary Rocket) # test-front — технический тестовый фронт (Binary Rocket)
Чисто технический веб-дашборд для **ручного тестирования механики экономики** Чисто технический веб-дашборд для **ручной проверки механики** через HTTP-шлюз:
(пополнение фантиками → ставка → вывод) БЕЗ Unity. Только кнопки + вывод технической кнопки + лог. Без Phantom, без swap, без вывода средств — только постановка ставок
информации и лог. Никакой «красоты» — он для гонок сценариев. фантиками и наблюдение за событиями.
## Зачем ## Зачем
Unity-фронт (`fun-game-front2`) хорош для продакшена, но для быстрых итераций по Технический пульт для проверки контракта «вручную»: быстро прогнать сценарий
экономике (swap ввод/вывод, ставка фантиками, поллинг результата) он тяжёлый. «создать кошелёк → пополнить тестовым фаусетом → поставить → дождаться исхода».
Этот фронт дёргает те же эндпоинты бэкенда и даёт мгновенный отклик. Полный контракт API (HTTP + WS, поля событий, коды ошибок) — **[API.md](API.md)**.
## Возможности ## Возможности
- Подключение Phantom, показ адреса. - Поля в шапке: **Шлюз (API)**, **WS URL**, **Адрес**.
- Отображение баланса: **фантики** (токен Binary Rocket) + SOL. - **Создать кошелёк** — генерирует новый custodial-адрес через шлюз.
- **Пополнить** — swap SOL→фантики через `POST /api/pump/swap` (подпись в Phantom). - **Пополнить кошелёк** — тестовый фаусет: наливает SOL и фантики.
- **Вывести** — swap фантики→SOL. - **Сделать ставку** — `POST /api/bet` (`side` `UP`/`DOWN`, `amountUnits`).
- **Ставка** (вверх/вниз) в фантиках через контракт: `GET /api/state` → - События по **WebSocket** (`price`, `bet_open`, `bet_closed`) — поллинга нет.
`POST /api/bet` → **события по WebSocket** (`bet_open` при постановке, `bet_closed` при
расчёте). Поллинг не нужен: шлюз закрывает ставку сам по таймеру.
Полный контракт API (HTTP + WS, поля событий, ошибки) — **[API.md](API.md)**.
- Лог всех действий + кнопки «Копировать» / «Очистить». - Лог всех действий + кнопки «Копировать» / «Очистить».
## Как пользоваться ## Как пользоваться
1. Открыть `index.html` (или раздать через любой статик-хостинг / nginx). 1. Открыть `https://testfront.binom.pw/` — `index.html` отдаётся из куба
2. В шапке задать конфиг: (namespace `game`). Поле «Шлюз (API)» можно оставить пустым — фронт возьмёт
- **API base** — бэкенд (напр. `https://smart-updown.binom.pw`). свой адрес.
- **RPC** — публичный Solana RPC (напр. `https://rpc.solanatracker.io/public`). 2. Нажать **Создать кошелёк** — в поле «Адрес» появится custodial-адрес.
- **Program** — адрес контракта (по умолч. `FMM...`). 3. Нажать **Пополнить кошелёк** — тестовый фаусет нальёт SOL и фантики.
- **Token mint** — адрес mint наших фантиков. 4. Выбрать сторону (`UP` / `DOWN`) и сумму (в пределах `minAmountHuman` /
3. Подключить Phantom. `maxAmountHuman` из `/api/state`: `100` … `10000` фантиков) → **Сделать ставку**.
4. Гонять сценарии: пополнить → сделать ставку → дождаться исхода → вывести. 5. Результат придёт сам по WS примерно через `expirySeconds` (15 с).
> Примечания Три возможных исхода ставки:
> - Фронт читает/пишет токен-аккаунты через RPC; для Token-2022 decimals читается из mint. - **выиграл** — `statusName: "payout_done"`, выплата с множителем;
> - STUB-ключи create_bet пока зашиты под SOL-версию контракта. Когда контракт переведут - **проиграл** — `statusName: "house_won"`, ставка остаётся в ваулте;
> на токен (Фаза 1), этот блок обновить под токеновые ключи. - **возврат при ничьей** — `statusName: "refunded"`, залог возвращён ровно
> - API base должен отдавать CORS (nginx-прокси), иначе браузер заблокирует fetch. суммой ставки без множителя (подробнее — [API.md](API.md), раздел
«Ничья при `exitPrice == entryPrice`»).
> Правило: **одна открытая ставка на адрес** — вторая ставка с того же адреса
> получит `409`. Дождитесь `bet_closed` по WS, прежде чем ставить снова.
## Статус ## Статус
- [x] каркас: балансы, swap ввод/вывод
- [x] ставка вверх/вниз через контракт (поллинг) - [x] каркас: кошелёк, фаусет, ставка, события по WS
- [ ] перевести подпись под токеновую версию контракта (после Фазы 1) - [x] контракт: возврат при ничьей (`exitPrice == entryPrice`)
- [ ] реальный провайдер цены вместо RandomPriceSource (за нами)