Files
pump-game-ops/docs/DECISIONS.md
T
subochev 30f851fb87 docs: ADR-008 (реализация цены из NATS) + PRICE-NATS.md + PlantUML (фаза 7)
ADR-007 (выбор источника binance-market/NATS) пришёл из другой сессии —
оставлен как есть, с апдейт-сноской. Реализация зафиксирована отдельным
ADR-008: NATS-консьюмер в шлюзе, цена x1e8 строковым парсером, раздача
фронту по WebSocket, деплой в k3s на testfront.binom.pw.
2026-09-13 05:58:05 +03:00

12 KiB
Raw Blame History

DECISIONS.md — журнал решений (ADR)

Каждое решение — короткая запись, чтобы потом не гадать, почему всё устроено так. Формат: дата, статус (принято/рассмотрение/заменено), суть, аргументы за/против, результат.


ADR-001 — Используем свой токен на pump.fun (мемкойн Binary Rocket)

  • Дата: 2026-09-09
  • Статус: принято
  • Суть: выпускаем СВОЙ токен на pump.fun, а не пользуемся чужим.
  • За: бренд/маркетинг, контроль экономики, стимул игрокам, единая валюта ставок.
  • Против: надо эмитировать и следить за курсом; чужой токен дал бы меньше работы.
  • Решение: свой токен. decimals = 6, Token-2022, создание через create_v2 (по доке pump.fun).

ADR-002 — Курс живой рыночный (Способ 1)

  • Дата: 2026-09-09
  • Статус: принято
  • Суть: вне игры баланс — в фантиках, курс берётся с рынка (bonding curve/AMM pump.fun). Ввод = swap SOL→фантики, вывод = swap фантики→SOL. Никакой фикс-привязки/стейблока.
  • За: нативно pump.fun, привычно игроку-трейдеру, технически проще, маркетинг (рост/падение токена).
  • Против: баланс «гуляет» с рынком; определённым аудиториям неудобно.
  • Решение: Способ 1. (Это и диктует, что ставки идут фантиками через контракт.)

ADR-003 — Ставки идут фантиками через контракт

  • Дата: 2026-09-09
  • Статус: принято (вытекает из ADR-002)
  • Суть: игрок ставит токен, контракт держит фантики в своём ATA-ваулте и платит фантиками.
  • Следствие: контракт переводится с нативного SOL (lamports) на SPL-токен — это ядро Фазы 1.
  • Против: трогаем хорошо работающий контракт; но без этого сценарий ввода-игры-вывода не работает.

ADR-004 — Ввод/вывод через pump.fun swap (POST /agents/swap)

  • Дата: 2026-09-09
  • Статус: принято
  • Суть: пополнение = inputMint: NATIVE_MINT(SOL), outputMint: наш_mint; вывод = наоборот. Клиент на бэкенде (Ktor PumpApiClient) уже готов в smart-updown-server.
  • За: возвращает готовую подписанную swap-транзакцию, бэкенд не держит ликвидность.
  • Против: весь ввод/вывод завязан на доступность pump.fun API.

ADR-05 (идея) — мета-репозиторий для документации и трекинга

  • Дата: 2026-09-09
  • Статус: принято
  • Суть: создать pump-game-ops, где живут карта репозиториев, решения, экономика и список задач.
  • За: единая точка оркестрации, не плаваем по чату. Против: риск превратиться во второй трекер.

ADR-005 — Флоу входа/вывода подтверждён (как описал юзер)

  • Дата: 2026-09-09
  • Статус: принято
  • Суть: человек заходит в игру → видит баланс 0 → кнопка «Пополнить» (одна, без выбора) → swap SOL→фантики → баланс появляется → ставит фантики через контракт (честное списание/начисление по исходу) → при выходе нажимает «Вывести» → swap фантики→SOL, баланс уменьшается.
  • За: точный пользовательский сценарий, подтверждённый владельцем; простая UX-модель.
  • Решение: именно так и работаем — это источник требований для Фазы 1 (контракт на токене) и Фазы 5 (UI).

ADR-006 — Предмет ставки: цена SOL (валюта — фантики)

  • Дата: 2026-09-09
  • Статус: принято
  • Суть: валютой ставки являются наши фантики (токен Binary Rocket), но ставка делается на направление цены SOL (вверх/вниз) — как и в текущей версии игры. Контракт по-прежнему сравнивает entry/exit_price цены SOL.
  • Цена SOL сейчас — случайная заглушка (RandomPriceSource). Позже заменяется на реальную (провайдер/оракул). Это отдельная задача, не блокирует Фазу 1 (контракт от способа получения цены не зависит). → Обновление 2026-09-11: реальный источник выбран — см. ADR-007.
  • Следствие: фантики = касса/валюта ввода-вывода; контракт оперирует токеном, но исход считает по цене SOL. Экономика токена (ADR-002 живой курс) не влияет на логику «вверх/вниз».

ADR-007 — Источник цены SOL = upstream-сервис binance-market

  • Дата: 2026-09-11
  • Статус: принято
  • Суть: цена SOL для PriceSource берётся из уже работающего в инвест-кластере сервиса binance-market (репо subochev/binance-market), а не из своей оракуль-логики и не из прямого опроса Binance. Контракт между игрой и сервисом — публичный:
    • NATS-подписка на топик market.price.solusdt (предпочтительно, в кластере); либо
    • WebSocket ws://<binance-market>:8080/ws/price?symbol=solusdt (fallback / внешние сети). Источник цены внутри binance-market — last-trade (aggTrade.p с биржи Binance), тики идут на каждой сделке → фактически real-time.
  • За:
    • Уже работает и развёрнут в кластере kube (ns invest), chart binom/binance-market, последний релиз v10. Не надо поднимать ещё один процесс ради цены.
    • Есть и NATS, и WS-контракт — обе формы потребления готовы.
    • Покрытие solusdt уже в списке символов; дополнительных подписок не требуется.
    • Цена приходит в тиках сделок (не сэмплинг раз в N секунд) — лучшее разрешение для сравнения entry/exit в round-based игре.
    • Общий сервис инвест-кластера, используется не только этой игрой; его судьба — не наша забота.
  • Против:
    • Один источник (Binance). Если Binance недоступен — игра без цены. Заглушка-fallback на RandomPriceSource остаётся как dev-only.
    • Зависимость по латентности от стороннего сервиса. В кластере это несколько мс, приемлемо.
  • Результат: задачи «TODO Цена SOL: реальный источник» (Фаза 0) и «PriceSource: реальная цена (вместо RandomPriceSource)» (Фаза 2) переводятся в IN_PROGRESS со ссылкой на это решение. Никаких новых подписок/оракулов не делаем — только интеграция в релейере (smart-updown-token/ relayer или smart-updown-server). Внешний статус сервиса см. README → «Внешние зависимости». → Обновление 2026-09-13: реализовано, см. ADR-008 (NATS-консьюмер в шлюзе, цена ×1e8, раздача фронту по WS).

ADR-008 — Реализация: цена SOL из NATS в шлюзе + раздача фронту по WS

  • Дата: 2026-09-13
  • Статус: принято, реализовано
  • Контекст: ADR-006 зафиксировал предмет ставки (цена SOL), ADR-007 выбрал источник (binance-market через NATS). Оставалось реализовать: сама цена была случайной заглушкой RandomPriceSource / simulated = 100_000_000 + Math.random(). Исход раунда был случаен, а не рыночен. При этом в контуре уже работает binance-market — сборщик сделок с Binance, который публикует каждую цену в NATS (market.price.<symbol>).
  • Решение: игровой шлюз (smart-updown-token/relayer) подписывается на NATS (market.price.solusdt) и берёт цену оттуда. Заглушка удалена.
    • Транспорт: core NATS nats://192.168.88.93:4222, subject market.price.solusdt. Режим — только чтение; binance-market не трогаем.
    • Шкала: строка из NATS переводится в целое ×1e8 строковым парсером (без float): "101.89000000" → 10189000000. То же юнит-пространство, что у оракульных цен и у прежней заглушки (100_000_000), поэтому контракт сравнивает цены корректно.
    • Раздача фронту: шлюз транслирует каждый тик по WebSocket (/ws, снаружи wss://testfront.binom.pw/api/ws), сообщение — только цена: {"type":"price","symbol":"solusdt","price":"102.30...","ts":...}.
    • Отсутствие цены: считается аварийным состоянием и обрабатывается мягко — шлюз стартует без NATS, запрос цены ждёт таймаут, фронт показывает последнее значение и переподключается. Отдельный сценарий деградации — тема для будущего решения.
  • За: исход раунда становится рыночным (entry/exit — реальные цены Binance); переиспользуется уже работающий сборщик, торговый контур не дублируется; шина отделяет источник цены от её потребителей (игра, аналитика, будущие сервисы).
  • Против: появляется зависимость от NATS и от binance-market; core NATS не хранит историю (нет JetStream) — при разрыве подписки цена не «догоняется», нужен живой поток.
  • Альтернативы: (а) прямая подписка шлюза на Binance WS — дублирование сборщика, лишние внешние коннекты; (б) оракул on-chain (Pyth/Switchboard) — правильнее для боя, но дороже и требует фидов; (в) заглушка — отклонено как единственный вариант, оставлена возможность (setPriceOverride) для тестов.
  • Детали и диаграммы: docs/PRICE-NATS.md, docs/diagrams/price-flow.puml.