# Инструменты проверки игрового контура Скрипты для **живой** приёмки механик ставок (не заменяют `npm test` в репозитории релейера, а проверяют боевой стенд). ## `exploit-decisive.cjs` — решающая проверка окна закрытия Проверяет главное: **цена закрытия берётся из истории на момент экспирации, а не в момент клика.** Как запускать (внутри пода шлюза — там есть `node_modules` и доступ к RPC): ```bash P=$(kubectl -n game get pod -l app.kubernetes.io/instance=testfront-gateway -o jsonpath='{.items[0].metadata.name}') kubectl -n game cp tools/exploit-decisive.cjs "$P:/app/data/probe/exploit-decisive.cjs" -c gateway kubectl -n game exec "$P" -c gateway -- sh -c "cd /app && node /app/data/probe/exploit-decisive.cjs 300" ``` ### Питфоллы (каждый пойман вживую) - **Нельзя просто сравнивать `exitPrice` с текущей ценой.** Цена часто стоит на месте, и сравнение вырождается в «совпало» — ложный успех. Скрипт ждёт, пока цена на экспирации и текущая **разойдутся**, и только тогда закрывает. Первый прогон без этого дал ложное «совпало» дважды. - **Копировать только в `/app/data/`**, не в `/app` (`Permission denied`, под не root). - **Запускать с `cd /app`**, иначе `Cannot find module '@solana/web3.js'` (из `/tmp`/`/app/data` без cwd `node_modules` не виден). - Ставка при `exit == entry` остаётся `open` — это ожидаемо (равные цены, отдельная задача), а не сбой проверки. Читает `bet_time` / `expire_time` прямо из аккаунта Bet (сырые байты) — off-chain данными не верим. Раскладка аккаунта (Anchor, после 8-байтового дискриминатора): `amount u64 @8`, `bet_time i64 @16`, `expire_time i64 @24`, `entry_price u64 @32`, `exit_price u64 @40`, `side u64 @48`, `status u64 @56`, `bettor Pubkey @64`. ## `price-history-probe.cjs` — разбор истории цены Смотрит, что реально накопилось в `binance-market` (Postgres `192.168.76.182:5434`, БД `binance_market`) вокруг конкретной ставки: сделки в окне, цена на входе, цена на экспирации, и что было бы при «ждать выгодной цены». ```bash node tools/price-history-probe.cjs ``` ⚠️ **Символ в БД — в нижнем регистре** (`solusdt`, не `SOLUSDT`). Запрос с верхним регистром вернёт пусто, и это легко принять за «данных нет».