feat(front): отдельный блок «Кошелёк и пополнение» на техтест-пульте

- кнопки «Создать кошелёк» (POST /wallet) и «Пополнить кошелёк» (GET /faucet)
- поле адреса кошелька + подстановка в поле «Адрес»
- подсказка про 403 в режиме release
- ставка: пояснение, что адрес обязателен и деньги выдаёт отдельная кнопка
This commit is contained in:
Caffeine
2026-09-13 13:38:38 +03:00
parent 83f6c77538
commit 707668b178
+47 -1
View File
@@ -70,6 +70,20 @@
<div id="stateInfo" class="info" style="margin-top:6px">Состояние ещё не прочитано.</div>
</fieldset>
<fieldset>
<legend>Кошелёк и пополнение (тест: POST /wallet, GET /faucet)</legend>
<div class="row">
<button onclick="gwWallet()">Создать кошелёк</button>
<button onclick="gwTopUp()">Пополнить кошелёк</button>
<span class="hint">Пополнение — только на тестовом стенде (на релизе шлюз ответит 403)</span>
</div>
<div class="row">
<label>Адрес кошелька</label><input id="walletAddr" size="46" readonly placeholder="(нажмите «Создать кошелёк»)"/>
<button onclick="useWalletAddr()">В поле «Адрес»</button>
</div>
<div class="hint">«Создать кошелёк» ничего не наливает: сначала создайте, затем нажмите «Пополнить кошелёк», потом ставьте.</div>
</fieldset>
<fieldset>
<legend>Ставка (POST /bet, без Phantom)</legend>
<div class="row">
@@ -81,7 +95,7 @@
</select>
<button onclick="gwBet()">Сделать ставку</button>
</div>
<div class="hint">сумма ×1e6 → units (decimals=6); адрес берётся из поля «Адрес» (пустой адрес — шлюз сам сгенерит и зарегистрирует кошелёк)</div>
<div class="hint">сумма ×1e6 → units (decimals=6). Адрес обязателен: сначала «Создать кошелёк» → «Пополнить кошелёк» (на тесте), затем ставка.</div>
<div class="hint" id="betLimits">лимиты ставок неизвестны (обновите state)</div>
</fieldset>
@@ -179,6 +193,38 @@ async function gwBalance(){
}catch(e){ log.err('balance: '+e.message); }
}
// ---- Кошелёк и пополнение (тест) ----
async function gwWallet(){
try{
const j = await gwFetch('/wallet', {});
document.getElementById('walletAddr').value = j.address || '';
log.ok('Кошелёк создан: '+j.address+' (денег на нём пока нет — нажмите «Пополнить кошелёк»)');
}catch(e){ log.err('wallet: '+e.message); }
}
async function gwTopUp(){
try{
const w = document.getElementById('walletAddr').value.trim();
const a = w || ADDR();
if(!a){ log.err('faucet: нет адреса — создайте кошелёк (или впишите адрес в поле «Адрес»)'); return; }
if(!w) document.getElementById('walletAddr').value = a;
const j = await gwFetch('/faucet/'+encodeURIComponent(a));
document.getElementById('balTok').textContent = j.tokenHuman;
document.getElementById('balSol').textContent = Number(j.sol).toFixed(6)+' SOL';
log.ok('Пополнено '+a+': фантики='+j.tokenHuman+', SOL='+j.sol);
}catch(e){
log.err('faucet: '+e.message);
if(String(e.message).indexOf('403')>=0) log.info('403 = пополнение выключено (режим release или сеть не тестовая). Это ожидаемо на боевом стенде.');
}
}
function useWalletAddr(){
const w = document.getElementById('walletAddr').value.trim();
if(!w){ log.err('в поле нет адреса кошелька — сначала «Создать кошелёк»'); return; }
document.getElementById('addr').value = w;
log.info('Адрес «'+w+'» подставлен в поле «Адрес» (для ставки и баланса)');
}
let lastBetId = '';
async function gwBet(){
try{