Skip to content

feat(websocket): implement WebSocket gateway and real-time event broa…#919

Merged
Olowodarey merged 3 commits into
Arena1X:mainfrom
Pvsaint:feat/websocket-gateway-and-realtime-events
May 31, 2026
Merged

feat(websocket): implement WebSocket gateway and real-time event broa…#919
Olowodarey merged 3 commits into
Arena1X:mainfrom
Pvsaint:feat/websocket-gateway-and-realtime-events

Conversation

@Pvsaint
Copy link
Copy Markdown
Contributor

@Pvsaint Pvsaint commented May 31, 2026

…dcasts

Closes #760 — [Backend] Implement WebSocket Gateway Closes #761 — [Backend] Implement Real-time Event Updates

═══════════════════════════════════════════════════════════ ISSUE #760 — WebSocket Gateway
═══════════════════════════════════════════════════════════

What was done:
Created src/websocket/events.gateway.ts — a NestJS WebSocket
gateway using @nestjs/websockets + socket.io (namespace /ws).

How it was done:
• Installed @nestjs/websockets, @nestjs/platform-socket.io, and
socket.io as runtime dependencies.
• EventsGateway implements OnGatewayConnection / OnGatewayDisconnect
for full lifecycle control.
• Connection authentication: on connect, the gateway reads a JWT
from handshake.auth.token or the Authorization header, verifies
it with JwtService, and auto-joins the authenticated user to their
personal user:{address} room.
• Room management supports three room patterns:
- event:{id} — scoped to a creator event
- match:{id} — scoped to a specific match
- user:{address} — private room for a single user
• join / leave message handlers validate room format with a regex
and enforce ownership for user rooms (unauthenticated clients
cannot join another user's room).
• Heartbeat: the gateway emits a ping every 25 s per connection;
the client is expected to respond with pong.
• Rate limiting: each socket is allowed 60 messages per 60-second
window; excess messages receive an error event.
• CORS: configured with origin '*' at the gateway decorator level
(tighten to specific origins in production via env config).
• WebsocketModule created (src/websocket/websocket.module.ts),
importing JwtModule with the app JWT_SECRET, and exporting
BroadcasterService so other modules can inject it.
• WebsocketModule registered in AppModule.
• Tests written in events.gateway.spec.ts covering: authenticated
connection, unauthenticated connection, invalid token, disconnect
cleanup, valid room joins (event/match/user), invalid room
rejection, user-room ownership enforcement, and rate limiting.

═══════════════════════════════════════════════════════════ ISSUE #761 — Real-time Event Updates / Broadcaster ═══════════════════════════════════════════════════════════

What was done:
Created src/websocket/broadcaster.service.ts — a service that
wraps EventsGateway.server and exposes typed broadcast methods
for every contract event type.

How it was done:
• BroadcasterService is an @Injectable() that receives
EventsGateway via constructor injection.
• One broadcast method per contract event type, each building a
consistent payload envelope { event, data } and targeting the
correct Socket.IO room(s):
- broadcastEventCreated → server.emit (all clients)
- broadcastEventUpdated → event:{id} room
- broadcastMatchAdded → event:{id} room
- broadcastUserJoined → event:{id} room
- broadcastPredictionSubmitted → event:{id} AND match:{id}
- broadcastMatchResolved → event:{id} AND match:{id}
- broadcastWinnersVerified → event:{id} room
- broadcastEventCancelled → event:{id} room
• Each method logs the broadcast target for observability.
• IndexerModule now imports WebsocketModule so IndexerService can
receive BroadcasterService via DI.
• IndexerService constructor updated to inject BroadcasterService.
• Every existing indexer event handler (handleEventCreated,
handleMatchAdded, handleUserJoinedEvent, handlePredictionSubmitted,
handleMatchResultSubmitted, handleWinnersVerified,
handleEventCancelled) now calls the corresponding broadcaster
method immediately after the notification generator call, so
real-time WebSocket pushes fire alongside in-app notifications.
• Tests written in broadcaster.service.spec.ts verifying that each
broadcast method calls server.emit / server.to with the correct
room name and event name.

…dcasts

Closes Arena1X#760 — [Backend] Implement WebSocket Gateway
Closes Arena1X#761 — [Backend] Implement Real-time Event Updates

═══════════════════════════════════════════════════════════
ISSUE Arena1X#760 — WebSocket Gateway
═══════════════════════════════════════════════════════════

What was done:
  Created src/websocket/events.gateway.ts — a NestJS WebSocket
  gateway using @nestjs/websockets + socket.io (namespace /ws).

How it was done:
  • Installed @nestjs/websockets, @nestjs/platform-socket.io, and
    socket.io as runtime dependencies.
  • EventsGateway implements OnGatewayConnection / OnGatewayDisconnect
    for full lifecycle control.
  • Connection authentication: on connect, the gateway reads a JWT
    from handshake.auth.token or the Authorization header, verifies
    it with JwtService, and auto-joins the authenticated user to their
    personal user:{address} room.
  • Room management supports three room patterns:
      - event:{id}   — scoped to a creator event
      - match:{id}   — scoped to a specific match
      - user:{address} — private room for a single user
  • join / leave message handlers validate room format with a regex
    and enforce ownership for user rooms (unauthenticated clients
    cannot join another user's room).
  • Heartbeat: the gateway emits a ping every 25 s per connection;
    the client is expected to respond with pong.
  • Rate limiting: each socket is allowed 60 messages per 60-second
    window; excess messages receive an error event.
  • CORS: configured with origin '*' at the gateway decorator level
    (tighten to specific origins in production via env config).
  • WebsocketModule created (src/websocket/websocket.module.ts),
    importing JwtModule with the app JWT_SECRET, and exporting
    BroadcasterService so other modules can inject it.
  • WebsocketModule registered in AppModule.
  • Tests written in events.gateway.spec.ts covering: authenticated
    connection, unauthenticated connection, invalid token, disconnect
    cleanup, valid room joins (event/match/user), invalid room
    rejection, user-room ownership enforcement, and rate limiting.

═══════════════════════════════════════════════════════════
ISSUE Arena1X#761 — Real-time Event Updates / Broadcaster
═══════════════════════════════════════════════════════════

What was done:
  Created src/websocket/broadcaster.service.ts — a service that
  wraps EventsGateway.server and exposes typed broadcast methods
  for every contract event type.

How it was done:
  • BroadcasterService is an @Injectable() that receives
    EventsGateway via constructor injection.
  • One broadcast method per contract event type, each building a
    consistent payload envelope { event, data } and targeting the
    correct Socket.IO room(s):
      - broadcastEventCreated   → server.emit (all clients)
      - broadcastEventUpdated   → event:{id} room
      - broadcastMatchAdded     → event:{id} room
      - broadcastUserJoined     → event:{id} room
      - broadcastPredictionSubmitted → event:{id} AND match:{id}
      - broadcastMatchResolved  → event:{id} AND match:{id}
      - broadcastWinnersVerified → event:{id} room
      - broadcastEventCancelled → event:{id} room
  • Each method logs the broadcast target for observability.
  • IndexerModule now imports WebsocketModule so IndexerService can
    receive BroadcasterService via DI.
  • IndexerService constructor updated to inject BroadcasterService.
  • Every existing indexer event handler (handleEventCreated,
    handleMatchAdded, handleUserJoinedEvent, handlePredictionSubmitted,
    handleMatchResultSubmitted, handleWinnersVerified,
    handleEventCancelled) now calls the corresponding broadcaster
    method immediately after the notification generator call, so
    real-time WebSocket pushes fire alongside in-app notifications.
  • Tests written in broadcaster.service.spec.ts verifying that each
    broadcast method calls server.emit / server.to with the correct
    room name and event name.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 31, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
insight-arena-4rll Ready Ready Preview, Comment May 31, 2026 5:28am

@drips-wave
Copy link
Copy Markdown

drips-wave Bot commented May 31, 2026

@Pvsaint Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Olowodarey Olowodarey merged commit 13bbbde into Arena1X:main May 31, 2026
5 checks passed
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.

[Backend] — Implement Real-time Event Updates [Backend] — Implement WebSocket Gateway

2 participants