diff --git a/index.html b/index.html index 0877dc1..5e0bb0a 100644 --- a/index.html +++ b/index.html @@ -100,12 +100,18 @@
- Закрытие (POST /close) + Ставка: ход игры (сервер закрывает сам)
- - - id заполнится после ставки, либо введите вручную + № ставки: — + состояние: нет ставки
+
+ вход: — + выход: — +
+
Ставку открывает кнопка «Сделать ставку» (HTTP). Итог приходит сам по WebSocket: + bet_open — ставка принята, bet_closed — рассчитана (примерно через 15 с). + Пока ставка открыта, вторую на этот адрес сервер не примет.
@@ -225,7 +231,11 @@ function useWalletAddr(){ log.info('Адрес «'+w+'» подставлен в поле «Адрес» (для ставки и баланса)'); } -let lastBetId = ''; +let liveBetId = ''; +function setLiveBet(field, value){ + const el = document.getElementById(field); + if(el) el.textContent = value; +} async function gwBet(){ try{ const side = document.getElementById('betSide').value; @@ -239,24 +249,33 @@ async function gwBet(){ const address = ADDR(); log.info('POST /bet side='+side+', amountUnits='+units.toString()+(address?' (address='+address+')':' (адрес пуст — шлюз сгенерит новый кошелёк)')); const j = await gwFetch('/bet', {side:side, amountUnits:units.toString(), address:address}); - lastBetId = String(j.id); - document.getElementById('closeId').value = lastBetId; + liveBetId = String(j.id); + setLiveBet('liveBetId', liveBetId); + setLiveBet('liveBetState', 'открыта, ждём закрытия (~15 с)'); + setLiveBet('liveBetEntry', String(j.entryPrice)); + setLiveBet('liveBetExit', '—'); log.ok('Ставка принята: id='+j.id+', bettor='+j.bettor+', entryPrice='+j.entryPrice+(j.tx?' tx='+j.tx:'')); if(!address) log.info('кошелёк шлюза: '+j.bettor+' (скопируйте в поле «Адрес» для дальнейших ставок)'); }catch(e){ log.err('bet: '+e.message); } } -async function gwClose(){ - try{ - const id = document.getElementById('closeId').value.trim(); - if(!id){ log.err('close: нет id ставки (сначала сделайте ставку или введите id вручную)'); return; } - const j = await gwFetch('/close', {id:id}); - const label = {payout_done:'ВЫИГРАЛ (payout_done)', house_won:'ПРОИГРАЛ (house_won)', open:'открыт (open)'}[j.statusName] || ('status='+j.statusName); - const detail = 'exitPrice='+j.exitPrice+(j.note?' — '+j.note:''); - if(j.statusName==='payout_done') log.ok('Закрыт #'+id+': '+label+', '+detail); - else if(j.statusName==='house_won') log.err('Закрыт #'+id+': '+label+', '+detail); - else log.info('Закрыт #'+id+': '+label+', '+detail); - }catch(e){ log.err('close: '+e.message); } +/** Событие WS: ставка открыта. */ +function onBetOpen(m){ + setLiveBet('liveBetId', String(m.id)); + setLiveBet('liveBetState', 'открыта ('+m.side+'), ждём закрытия'); + setLiveBet('liveBetEntry', String(m.entryPrice)); + setLiveBet('liveBetExit', '—'); + log.info('bet_open: #'+m.id+' '+m.side+', сумма='+m.amountUnits+', вход='+m.entryPrice); +} + +/** Событие WS: ставка рассчитана — сервер закрыл её сам. */ +function onBetClosed(m){ + setLiveBet('liveBetId', String(m.id)); + const won = m.statusName === 'payout_done'; + setLiveBet('liveBetState', won ? 'ВЫИГРАЛ (payout_done)' : 'ПРОИГРАЛ (house_won)'); + setLiveBet('liveBetExit', String(m.exitPrice)); + const text = 'bet_closed: #'+m.id+', выход='+m.exitPrice+', '+(won?'ВЫИГРАЛ':'ПРОИГРАЛ'); + if(won) log.ok(text); else log.err(text); } function copyLog(){ const t=document.getElementById('log').innerText; navigator.clipboard?.writeText(t).then(()=>log.ok('лог скопирован')).catch(()=>{}); } @@ -338,7 +357,11 @@ function connectWs(){ ws.onmessage = (ev) => { let m; try{ m = JSON.parse(ev.data); }catch(e){ return; } - if(!m || m.type !== 'price') return; + if(!m || !m.type) return; + // Клиентские события жизненного цикла ставки — сервер закрывает ставку сам. + if(m.type === 'bet_open'){ onBetOpen(m); return; } + if(m.type === 'bet_closed'){ onBetClosed(m); return; } + if(m.type !== 'price') return; wsMsgCount++; document.getElementById('wsMsgCount').textContent = String(wsMsgCount); const fullPrice = String(m.price);