Hero hole cards render face down after ~1h on a table (auth signature never renewed)

Closed
#953 0 comments 0 reactions 2 assignees View on GitHub

Maintainers usually reply within 1 day

@bitcoinbrisbane is already working on this.

Since Nov 2, 2026.

Assessment

This issue has not been assessed yet.

Description

bug UI Week 2

Summary

Several nights recently, a seated player was dealt hole cards that rendered face down (card backs) to that player. Everyone else's view looked normal. A browser refresh fixes it immediately. Related symptom previously reported in #409 (closed without an identified root cause).

Likely root cause (inferred from code, ~80% confidence)

The per-player websocket auth is signed once per socket and never renewed. After ~1 hour, the chain rejects it, and the relay silently falls back to the public (fully masked) state.

  1. UI signs once. src/context/GameStateContext.tsx (block52/ui main, L302-310): on socket open, createAuthPayload() signs pokerchain-query:<unix ts> and sends a single subscribe {gameId, playerAddress, timestamp, signature}. Nothing re-signs while the socket stays open. The wake handler (L462-485) returns early for an open, live socket (L473), so a tab becoming visible does not re-sign either.
  2. Relay keeps the first signature forever. block52/pokerchain pkg/wsserver/server.go L806-810 stores playerId/timestamp/signature on the client at subscribe. Every broadcast (sendPersonalizedUpdate, L538+, and authedStateJSON in optimistic.go L159-186) reuses them.
  3. Silent masked fallback. On any error from the authenticated GameState / OptimisticGameState query, the relay falls back to the public Game query (server.go ~L462-473 and L565-568), where all hole cards are masked. No error is sent to the client.
  4. Chain 1h window. x/poker/keeper/query_game_state.go L47-56 (and query_optimistic_game_state.go L39) reject a timestamp more than 1 hour from block time.

So ~60 min after the socket opened, every update reaches the hero with their own cards as X, and the seat draws backs. A refresh re-signs, which is why it fixes it.

Possible trigger for it showing up now: #910 (fix for #867) stopped a browser offline blip from tearing down an open socket. Previously those blips likely forced reconnects, and each reconnect quietly re-signed. Sockets now live longer than 1h more often. This is unverified.

How to confirm

  • Relay logs for the affected player should show the authenticated query failing with timestamp must be within 1 hour of block time, followed by the public-query fallback.
  • Repro: sit at a table for more than 60 min without refreshing. Hole cards should go face down at about the hour mark.

Load impact of the fix

One extra read-only signed query per player every 30-45 min (re-subscribe returns a fresh snapshot). No indexer involvement, negligible device cost.

Proposed fix

  • Periodically re-sign and re-send subscribe on the same socket every 30-45 min. The relay already overwrites stored credentials on a new subscribe. Apply the snapshot as a normal state update, without bus.reset().
  • Re-sign and re-subscribe when the tab becomes visible again (visibilitychange).
  • Debounced safety net: if the hero is seated in a live hand and their own hole cards arrive masked (X/??), re-subscribe with a fresh signature once, with a debounce to avoid loops.
  • Follow-up for block52/pokerchain (relay): when a client's authenticated query fails, send an auth_expired event (or keep the last per-player state) instead of silently serving the public masked state, and log it clearly.

Code refs: block52/ui main 12b9a929, block52/pokerchain v0.1.206 da56cd6.

Dominant language
TypeScript
Stars
2
Forks
5
Avg merge
21h 50m
Merged PRs (30d)
104

Getting set up

We have not checked this project's setup files yet. Start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from block52/ui

All issues in block52/ui

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.