Skip to content

Unify bets playback, market parity, and keeper recovery#130

Open
rndrntwrk wants to merge 174 commits into
mainfrom
enoomian/unified-bets-parity-keepers
Open

Unify bets playback, market parity, and keeper recovery#130
rndrntwrk wants to merge 174 commits into
mainfrom
enoomian/unified-bets-parity-keepers

Conversation

@rndrntwrk

@rndrntwrk rndrntwrk commented Apr 18, 2026

Copy link
Copy Markdown
Collaborator

Table of Contents

  • Summary
  • Scope
  • Critical Fixes Since Review
  • Rollout
  • Key Changes
  • Validation
  • Review Guidance

Summary

This PR aligns bettor-visible market state with the actual duel stream, hardens playback and market-parity behavior in the unified apps, and improves keeper recovery, auth, and result lookup behavior across the active rails.

Scope

This PR covers five linked areas:

  1. canonical session and source-time propagation
  2. viewer-aligned bettor state and UI gating
  3. playback, parity, and trade-gate behavior in the unified apps
  4. keeper recovery, auth, and result lookup hardening
  5. supporting registry / IDL / acceptance-tooling changes carried by this branch

Critical Fixes Since Review

Reviewers from earlier cycles flagged regressions that have been addressed on this branch. Each item below maps to a specific commit with test coverage. This PR exceeds GitHub's standard diff rendering limit, so this section is the reviewer-facing index for the fixes landed after review.

  • Canonical preload is now lifecycle-gated - fix(ui): gate canonical preload on lifecycle identity (e498a6e4). packages/hyperbet-ui/src/lib/streamSession.ts now applies the canonical-session / lifecycle match gate to both active playback and preload selection, so a mismatched canonical rail cannot still mount through activeStreamUrl || preloadStreamUrl.
  • Missing canonical duel identity now fails closed - same commit. When the lifecycle already knows the active duelId or duelKey, a canonical session with neither identifier is rejected instead of being treated as a match for any duel.
  • EVM and BSC keepers republish same-duel readiness and authority changes - fix(keeper): republish same-duel authority changes (15a3a561). Poll-mode publication now compares the public stream-state surface, not only cycleId, phase, and winnerId, so readiness, authority, source-runtime, and delivery-health changes can propagate within the same duel.
  • Public stream-state dedupe ignores volatile telemetry churn - fix(keeper): ignore volatile stream telemetry churn (657a59b3). publicStreamStateChanged now compares stable public fields instead of hashing raw cycle / timeline objects with timestamp-only churn.
  • Regression coverage was added for selector gating and poll-mode dedupe - expanded coverage lives in packages/hyperbet-ui/tests/streamSession.test.ts and packages/hyperbet-{evm,bsc}/keeper/src/betSync.test.ts.

Rollout

The viewer-alignment path is gated by VITE_ENABLE_VIEWER_ALIGNED_BET_STATE and defaults off unless explicitly enabled. With the flag off, the adapter path remains inert and bettor panels continue to read the canonical state path.

Key Changes

1. Canonical session and source-time propagation

  • carries source/server emission timing through keeper-facing surfaces
  • preserves raw source-timeline data across the active keeper rails
  • tightens canonical stream-session handling so bettor-visible state can align to stream time rather than freshest wall clock alone

2. Viewer-aligned bettor state

  • adds viewer clock, rail buffering, and snapshot-selection logic
  • wires aligned state into the unified app shells behind the feature flag
  • threads aligned display overrides into the bettor panels so visible phase/open/lock state can follow the viewed stream frame

3. Playback, parity, and trade-gate behavior

  • fixes stream-player status propagation in the unified apps
  • hardens trade-gate and playback-progress handling
  • fixes parity/pre-fight copy behavior observed on the bettor surface
  • carries the app-side playback and acceptance-environment adjustments required by the unified path

4. Keeper recovery, auth, and result lookup

  • aligns result catch-up auth with the provider path
  • narrows result lookup token handling
  • preserves source-time fields across sibling keeper rails
  • carries the related keeper-side recovery and transport fixes on this branch

5. Supporting registry / IDL / tooling updates

  • includes the branch-carried registry, IDL, and acceptance-tooling updates that move with these runtime surfaces

Validation

Validation for this PR has included targeted coverage across the touched surfaces, including:

  • EVM / BSC / Solana keeper typechecks
  • viewer-alignment unit coverage
  • targeted bettor UI and parity behavior tests
  • end-to-end verification of the unified bettor playback path

Review Guidance

Suggested review order:

  1. keeper timestamp / source-time propagation
  2. viewer-alignment core and selector logic
  3. unified app and bettor UI integration
  4. keeper auth / recovery / result lookup changes
  5. registry / IDL / tooling updates carried by the branch

rndrntwrk and others added 30 commits March 31, 2026 00:05
fix: split shared rpc reads from submit paths
Add per-chain keeper URL variables to the CI matrix so each package
build resolves VITE_GAME_API_URL from its own GitHub variable
(HYPERBET_SOLANA_KEEPER_URL, HYPERBET_BSC_KEEPER_URL, etc.) with
public-facing domains preserved as last-resort fallbacks.

Restore public domains in client config.ts defaults replacing
Railway infrastructure URLs that were previously hardcoded.
fix: route CI builds through chain-specific keeper variables
…ment

docs: align release tracking with active scope
…pers

# Conflicts:
#	bun.lock
#	packages/hyperbet-bsc/app/src/App.tsx
#	packages/hyperbet-evm/app/src/App.tsx
#	packages/hyperbet-solana/app/src/App.tsx
#	packages/hyperbet-ui/tests/predictionMarkets.test.ts
Three CI fixes for the unified-bets-parity-keepers branch:

1. `ci(prediction-market-gates)`: switch the Playwright browser install
   from `bunx playwright install` to the app package's
   `./node_modules/.bin/playwright`. `bunx` pulls the latest Playwright
   CLI from npm, which now ships chromium v1217, but
   `@playwright/test@1.58.2` expects v1208. The mismatch caused
   `browserType.launch: Executable doesn't exist at
   chromium_headless_shell-1208` on every Unified Bets E2E run after
   the Apr 23 CLI republish.

2. `fix(ui/streamSession)`: import `normalizePredictionMarketDuelKeyHex`
   directly from `@hyperbet/chain-registry` rather than from
   `./predictionMarkets`. The previous indirection created the cycle
   `predictionMarkets → config → streamSession → predictionMarkets`
   and caused `ReferenceError: Cannot access 'GAME_API_URL' before
   initialization` on page load, because `predictionMarkets`'s
   module-level URL consts were evaluated before `config` had
   assigned `GAME_API_URL`. `predictionMarkets` re-exports the
   function as-is, so routing callers through the registry
   breaks the cycle without changing behaviour.

3. `fix(keeper/betSync.test)`: annotate the three new
   `publicStreamStateChanged` test fixtures as `StreamState`. The
   partial mock objects were tripping `TS2345` because
   `BetSyncCanonicalAuthority` has thirteen non-optional fields and
   the fixtures only populate the subset the tests care about; the
   function only inspects via JSON.stringify so the cast is safe.
My earlier `as StreamState` cast tripped TS2352 ("types may be a mistake
because neither type sufficiently overlaps") — the fixture shape is a
narrow subset of `StreamState` (especially
`BetSyncCanonicalAuthority`'s 13 required fields), and TS refuses a
direct cast between insufficiently-overlapping types. Route through
`as unknown as StreamState` as the error message literally
recommends. No runtime change; the three fixtures still flow into
`publicStreamStateChanged` as before and its JSON.stringify
comparison works on whatever properties are actually present.
@rndrntwrk rndrntwrk marked this pull request as ready for review April 24, 2026 09:40
@rndrntwrk rndrntwrk marked this pull request as draft April 28, 2026 17:08
@rndrntwrk rndrntwrk marked this pull request as ready for review April 28, 2026 17:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants