1k-adding-socket-events
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
EAppSocketEventNamesenum - 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:
1. Event Name (socket.ts)
export enum EAppSocketEventNames {
// ... other events
userInfoUpdated = 'USER_INFO_UPDATED',
}
2. Payload Type (socket.ts)
export interface IUserInfoUpdatedPayload {
msgId: string;
}
3. 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
EAppSocketEventNamesenum - 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