Adding WebSocket Event Subscriptions
This skill documents how to add new WebSocket event subscriptions in the OneKey app.
Overview
WebSocket events enable real-time server-to-client communication. The pattern involves:
-
Define the event name in EAppSocketEventNames enum
-
Define the payload type interface
-
Add the event handler in PushProviderWebSocket
Key Files
Purpose Location
Event names & payload types packages/shared/types/socket.ts
WebSocket event handlers packages/kit-bg/src/services/ServiceNotification/PushProvider/PushProviderWebSocket.ts
Step-by-Step Guide
Step 1: Define Event Name
Add the new event name to EAppSocketEventNames in packages/shared/types/socket.ts :
export enum EAppSocketEventNames { notification = 'notification', ping = 'ping', pong = 'pong', ack = 'ack', market = 'market', primeConfigChanged = 'CONFIG_CHANGE', // ... existing events myNewEvent = 'MY_NEW_EVENT', // Add your new event }
Convention: Use camelCase for the enum key, SCREAMING_SNAKE_CASE for the string value.
Step 2: Define Payload Type
Add the payload interface in packages/shared/types/socket.ts :
export interface IMyNewEventPayload { msgId: string; // Required for acknowledgment // Add other fields as needed someData?: string; someNumber?: number; }
Important: Always include msgId: string for message acknowledgment.
Step 3: Add Event Handler
In packages/kit-bg/src/services/ServiceNotification/PushProvider/PushProviderWebSocket.ts :
- Import the new payload type:
import type { // ... existing imports IMyNewEventPayload, } from '@onekeyhq/shared/types/socket';
- Add the event handler in initWebSocket() method:
this.socket.on(EAppSocketEventNames.myNewEvent, (payload: IMyNewEventPayload) => { // 1. Acknowledge receipt (required for most events) void this.backgroundApi.serviceNotification.ackNotificationMessage({ msgId: payload.msgId, action: ENotificationPushMessageAckAction.arrived, });
// 2. Handle the event (call appropriate service method) void this.backgroundApi.someService.handleMyNewEvent(payload); });
Complete Example: userInfoUpdated Event
Here's a real example from the codebase:
- Event Name (socket.ts)
export enum EAppSocketEventNames { // ... other events userInfoUpdated = 'USER_INFO_UPDATED', }
- Payload Type (socket.ts)
export interface IUserInfoUpdatedPayload { msgId: string; }
- Event Handler (PushProviderWebSocket.ts)
this.socket.on(EAppSocketEventNames.userInfoUpdated, (payload: IUserInfoUpdatedPayload) => { void this.backgroundApi.serviceNotification.ackNotificationMessage({ msgId: payload.msgId, action: ENotificationPushMessageAckAction.arrived, }); void this.backgroundApi.servicePrime.apiFetchPrimeUserInfo(); });
Event Handler Patterns
Simple Acknowledgment + Action
this.socket.on(EAppSocketEventNames.myEvent, (payload: IMyPayload) => { void this.backgroundApi.serviceNotification.ackNotificationMessage({ msgId: payload.msgId, action: ENotificationPushMessageAckAction.arrived, }); void this.backgroundApi.someService.doSomething(); });
With Logging
this.socket.on(EAppSocketEventNames.myEvent, (payload: IMyPayload) => { defaultLogger.notification.websocket.consoleLog( 'WebSocket received myEvent:', payload, ); void this.backgroundApi.serviceNotification.ackNotificationMessage({ msgId: payload.msgId, action: ENotificationPushMessageAckAction.arrived, }); void this.backgroundApi.someService.doSomething(payload); });
With Validation
this.socket.on(EAppSocketEventNames.myEvent, async (payload: IMyPayload) => { if (!payload?.requiredField) { console.error('myEvent ERROR: requiredField is missing', payload); return; } void this.backgroundApi.serviceNotification.ackNotificationMessage({ msgId: payload.msgId, action: ENotificationPushMessageAckAction.arrived, }); await this.backgroundApi.someService.doSomething(payload); });
With EventBus Emission
this.socket.on(EAppSocketEventNames.myEvent, (payload: IMyPayload) => { void this.backgroundApi.serviceNotification.ackNotificationMessage({ msgId: payload.msgId, action: ENotificationPushMessageAckAction.arrived, }); appEventBus.emit(EAppEventBusNames.MyEventReceived, payload); });
Important: Message Acknowledgment
You MUST acknowledge messages via serviceNotification.ackNotificationMessage . If you don't acknowledge the msgId , the server will assume the message was not delivered and will retry sending it repeatedly.
void this.backgroundApi.serviceNotification.ackNotificationMessage({ msgId: payload.msgId, action: ENotificationPushMessageAckAction.arrived, });
This should be called as early as possible in your event handler to prevent duplicate message delivery.
Acknowledgment Actions
Available actions in ENotificationPushMessageAckAction :
-
arrived
-
Message was received (use this for most cases)
-
clicked
-
User clicked the notification
Checklist
-
Event name added to EAppSocketEventNames enum
-
Payload interface defined with msgId: string
-
Payload type imported in PushProviderWebSocket.ts
-
Event handler added in initWebSocket() method
-
Message acknowledged via ackNotificationMessage (required to prevent server retries)
-
Appropriate service method called to handle the event
-
Logging added if needed for debugging