fix(api): рабочий рецепт — /api в базе обязателен для POST

Найдено исполнением рецепта из самого файла: `const BASE = 'https://testfront.binom.pw'`
→ `POST /wallet` возвращал 405 Method Not Allowed. GET-ручки терпят отсутствие
префикса (`/state` == `/api/state`), а POST-ручки — нет. Внешний разработчик
спотыкался на первой же строке примера.

Что исправлено:
- база в примере: `https://testfront.binom.pw/api` + предупреждение про /api
- POST /wallet в примере: добавлены заголовок Content-Type и тело `{}` (без них 405)
- WS-адрес в примере: явный `wss://` вместо `BASE.replace('https','wss')`,
  который после смены базы дал бы кривой `wss://testfront.binom.pw/api.replace…`
- amountUnits в примере — строкой (поддержаны оба вида, число тоже работает)

Проверено: рецепт, выдранный из файла регуляркой и запущенный как есть, отдаёт
курс, `bet_open` и `bet_closed`. WS принимает подключение с чужого Origin
(проверено тремя вариантами заголовка).
This commit is contained in:
Caffeine
2026-09-14 02:32:32 +03:00
parent b8c040dedc
commit 07e00f106c
+12 -7
View File
@@ -4,10 +4,14 @@
и получать события в реальном времени. Источник — код шлюза и получать события в реальном времени. Источник — код шлюза
(`smart-updown-token/relayer/src/gateway.ts`, `settle.ts`). (`smart-updown-token/relayer/src/gateway.ts`, `settle.ts`).
**База:** `https://testfront.binom.pw` **База:** `https://testfront.binom.pw/api`
Пути нормализуются: `/api/state` и `/state` — одно и то же.
CORS открыт (`Access-Control-Allow-Origin: *`) — можно дёргать прямо из браузера. CORS открыт (`Access-Control-Allow-Origin: *`) — можно дёргать прямо из браузера.
> ⚠️ **`/api` в базе обязателен.** GET-ручки (`/state`, `/price`, `/balance`, `/faucet`)
> отвечают и без префикса — `…/state` и `…/api/state` одно и то же. Но **POST-ручки
> (`/wallet`, `/bet`) без `/api` не работают**: `POST …/wallet` → `405 Method Not Allowed`.
> Держите `/api` в базе, и всё будет единообразно.
**Стенд тестовый** (`SMART_MODE=test`): фантики фейковые, SOL из фаусета, контракт наш. **Стенд тестовый** (`SMART_MODE=test`): фантики фейковые, SOL из фаусета, контракт наш.
--- ---
@@ -15,14 +19,15 @@ CORS открыт (`Access-Control-Allow-Origin: *`) — можно дёргат
## Короткий рецепт: «поставить и получить события» ## Короткий рецепт: «поставить и получить события»
```js ```js
const BASE = 'https://testfront.binom.pw'; const BASE = 'https://testfront.binom.pw/api'; // /api обязателен, см. выше
const H = { 'Content-Type': 'application/json' };
// 1. Кошелёк + деньги (только test-mode) // 1. Кошелёк + деньги (только test-mode)
const { address } = await (await fetch(`${BASE}/wallet`, { method: 'POST' })).json(); const { address } = await (await fetch(`${BASE}/wallet`, { method: 'POST', headers: H, body: '{}' })).json();
await fetch(`${BASE}/faucet/${address}`); // наливает 5 SOL + 10 000 фантиков await fetch(`${BASE}/faucet/${address}`); // наливает 5 SOL + 10 000 фантиков
// 2. Подписка на события // 2. Подписка на события
const ws = new WebSocket(`${BASE.replace('https', 'wss')}/api/ws`); const ws = new WebSocket('wss://testfront.binom.pw/api/ws'); // только wss: страница по HTTPS
ws.onmessage = (e) => { ws.onmessage = (e) => {
const m = JSON.parse(e.data); const m = JSON.parse(e.data);
if (m.type === 'price') console.log('курс ', m.price); // "101.02" if (m.type === 'price') console.log('курс ', m.price); // "101.02"
@@ -33,8 +38,8 @@ ws.onmessage = (e) => {
// 3. Ставка. ВНИМАНИЕ: поле называется amountUnits, НЕ amount! // 3. Ставка. ВНИМАНИЕ: поле называется amountUnits, НЕ amount!
await fetch(`${BASE}/bet`, { await fetch(`${BASE}/bet`, {
method: 'POST', method: 'POST',
headers: { 'Content-Type': 'application/json' }, headers: H,
body: JSON.stringify({ address, side: 'UP', amountUnits: 500000000 }), // 500 фантиков body: JSON.stringify({ address, side: 'UP', amountUnits: '500000000' }), // 500 фантиков
}); });
// Закрывать не нужно — шлюз закроет сам по таймеру (см. «Авто-закрытие»). // Закрывать не нужно — шлюз закроет сам по таймеру (см. «Авто-закрытие»).
``` ```