Setup
Pegue o projeto
git clone git@github.com:GambaLabs/slotbattle-demo-casino.git
cd slotbattle-demo-casino
npm install
Configure
cp .env.example .env
SLOTBATTLE_BASE_URL=http://127.0.0.1:8070
SLOTBATTLE_API_KEY=sbk_0a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f9
SLOTBATTLE_WEBHOOK_SECRET=um-segredo-que-voce-tambem-define-no-console
SLOTBATTLE_WS_BASE_URL=
DEMO_GAME_ID=sweet-bonanza
DEMO_CREATOR_GAME_URL=
DEMO_CREATOR_GAME_URL é opcional. Deixe vazio e a demo emite uma sessão para o assento do
criador a cada batalha. Preencha quando você tiver uma sessão para reusar sempre, ou quando a
emissão não estiver disponível para você. Veja Primeira batalha.
Nenhum desses nomes carrega prefixo VITE_ ou NEXT_PUBLIC_, então nenhum deles chega ao
bundle do cliente.
A chave de API é uma credencial servidor a servidor que cobre o seu casino inteiro. Qualquer coisa que a tenha pode abrir batalhas, sentar bots e ler todas as suas batalhas.
Ela nunca pode chegar a um browser: nem num bundle, nem numa prop, nem num
window.__CONFIG__. Toda chamada ao SlotBattle neste projeto passa por um route handler no
servidor.
O cliente de API impõe isso já no import:
if (typeof window !== 'undefined') {
throw new Error(
'lib/slotbattle must never be imported into client code — it reads the API key.',
)
}
Importar esse módulo de um componente de cliente falha naquele import em vez de enviar uma credencial ao browser.
Rode
npm run dev # http://127.0.0.1:5174
A página de lobby renderiza o catálogo. Jogos na tela confirmam três coisas de uma vez: a URL base, a chave e a allowlist.
Se o catálogo vier vazio
No games allowed for this casino yet.
Isso é configuração, não erro. Uma allowlist vazia retorna um catálogo vazio; não significa "todos os jogos".
Libere o jogo na tela de jogos do console, se você tiver acesso, ou peça ao seu host.
A mudança normalmente aparece na hora, mas a allowlist é cacheada por 30 segundos e a invalidação pode se perder no caminho. Se o catálogo continuar vazio logo depois de o seu host confirmar a mudança, espere até 30 segundos antes de depurar qualquer outra coisa. Esse é o sintoma mais mal diagnosticado do SlotBattle.
Outras coisas que podem dar errado aqui
| Sintoma | Causa |
|---|---|
unauthorized | Chave errada, ou revogada. Chave perdida não se recupera, então emita uma nova |
forbidden: missing scope: ... | Falta um escopo na chave, nomeado na mensagem. demo:mint é o que falta em chaves antigas |
| Não alcança o SlotBattle | SLOTBATTLE_BASE_URL errada, ou a instância caiu. Tente curl $BASE/health |
O formato do projeto
app/
page.tsx lobby: catálogo, abrir batalha, lobbies abertos
_components/
open-battle-form.tsx cliente — abre a batalha e senta os bots
battles/[id]/
page.tsx servidor — busca o snapshot
_components/live-battle.tsx cliente — WebSocket + HLS
api/
games/route.ts ─┐
battles/route.ts │ proxy no servidor: o ÚNICO lugar
battles/[id]/route.ts │ onde a chave de API é lida
battles/[id]/bot-seats/ │
battles/[id]/viewer-token/ ─┘
webhooks/slotbattle/route.ts resultado com assinatura verificada
lib/
slotbattle.ts cliente de API tipado (só servidor)
webhook-signature.ts verificação de HMAC
settlements.ts onde um casino real creditaria a carteira
Duas fronteiras aparecem nessa árvore: lib/slotbattle.ts é importado só por app/api/* e por
componentes de servidor, e componentes de cliente só chamam /api/* na nossa própria origem.