@@ -15,9 +15,9 @@ import type {
15
15
} from './types' ;
16
16
import type { AccountActivityServiceMethodActions } from './AccountActivityService-method-action-types' ;
17
17
import type {
18
- WebSocketService ,
19
18
WebSocketConnectionInfo ,
20
19
WebSocketServiceConnectionStateChangedEvent ,
20
+ SubscriptionInfo ,
21
21
} from './WebsocketService' ;
22
22
import { WebSocketState } from './WebsocketService' ;
23
23
@@ -72,6 +72,14 @@ export const ACCOUNT_ACTIVITY_SERVICE_ALLOWED_ACTIONS = [
72
72
'AccountsController:getAccountByAddress' ,
73
73
'AccountsController:getSelectedAccount' ,
74
74
'TokenBalancesController:updateBalances' ,
75
+ 'BackendWebSocketService:connect' ,
76
+ 'BackendWebSocketService:disconnect' ,
77
+ 'BackendWebSocketService:isChannelSubscribed' ,
78
+ 'BackendWebSocketService:getSubscriptionByChannel' ,
79
+ 'BackendWebSocketService:findSubscriptionsByChannelPrefix' ,
80
+ 'BackendWebSocketService:addChannelCallback' ,
81
+ 'BackendWebSocketService:removeChannelCallback' ,
82
+ 'BackendWebSocketService:sendRequest' ,
75
83
] as const ;
76
84
77
85
// Allowed events that AccountActivityService can listen to
@@ -92,6 +100,38 @@ export type AccountActivityServiceAllowedActions =
92
100
| {
93
101
type : 'TokenBalancesController:updateBalances' ;
94
102
handler : ( options ?: { chainIds ?: string [ ] ; queryAllAccounts ?: boolean } ) => Promise < void > ;
103
+ }
104
+ | {
105
+ type : 'BackendWebSocketService:connect' ;
106
+ handler : ( ) => Promise < void > ;
107
+ }
108
+ | {
109
+ type : 'BackendWebSocketService:disconnect' ;
110
+ handler : ( ) => Promise < void > ;
111
+ }
112
+ | {
113
+ type : 'BackendWebSocketService:isChannelSubscribed' ;
114
+ handler : ( channel : string ) => boolean ;
115
+ }
116
+ | {
117
+ type : 'BackendWebSocketService:getSubscriptionByChannel' ;
118
+ handler : ( channel : string ) => SubscriptionInfo | undefined ;
119
+ }
120
+ | {
121
+ type : 'BackendWebSocketService:findSubscriptionsByChannelPrefix' ;
122
+ handler : ( channelPrefix : string ) => SubscriptionInfo [ ] ;
123
+ }
124
+ | {
125
+ type : 'BackendWebSocketService:addChannelCallback' ;
126
+ handler : ( options : { channelName : string ; callback : ( notification : any ) => void } ) => void ;
127
+ }
128
+ | {
129
+ type : 'BackendWebSocketService:removeChannelCallback' ;
130
+ handler : ( channelName : string ) => boolean ;
131
+ }
132
+ | {
133
+ type : 'BackendWebSocketService:sendRequest' ;
134
+ handler : ( message : any ) => Promise < any > ;
95
135
} ;
96
136
97
137
// Event types for the messaging system
@@ -154,17 +194,16 @@ export type AccountActivityServiceMessenger = RestrictedMessenger<
154
194
* - Comprehensive balance updates with transfer tracking
155
195
*
156
196
* Architecture:
157
- * - WebSocketService manages the actual WebSocket subscriptions and callbacks
158
- * - AccountActivityService only tracks channel-to-subscriptionId mappings
197
+ * - Uses messenger pattern to communicate with BackendWebSocketService
198
+ * - AccountActivityService tracks channel-to-subscriptionId mappings via messenger calls
159
199
* - Automatically subscribes to selected account on initialization
160
200
* - Switches subscriptions when selected account changes
161
- * - No duplication of subscription state between services
201
+ * - No direct dependency on WebSocketService (uses messenger instead)
162
202
*
163
203
* @example
164
204
* ```typescript
165
205
* const service = new AccountActivityService({
166
206
* messenger: activityMessenger,
167
- * webSocketService: wsService,
168
207
* });
169
208
*
170
209
* // Service automatically subscribes to the currently selected account
@@ -183,26 +222,22 @@ export class AccountActivityService {
183
222
184
223
readonly #messenger: AccountActivityServiceMessenger ;
185
224
186
- readonly #webSocketService: WebSocketService ;
187
-
188
225
readonly #options: Required < AccountActivityServiceOptions > ;
189
226
190
- // WebSocketService is the source of truth for subscription state
191
- // Using WebSocketService. findSubscriptionsByChannelPrefix() for cleanup
227
+ // BackendWebSocketService is the source of truth for subscription state
228
+ // Using BackendWebSocketService: findSubscriptionsByChannelPrefix() for cleanup
192
229
193
230
/**
194
231
* Creates a new Account Activity service instance
195
232
*
196
- * @param options - Configuration options including messenger and WebSocket service
233
+ * @param options - Configuration options including messenger
197
234
*/
198
235
constructor (
199
236
options : AccountActivityServiceOptions & {
200
237
messenger : AccountActivityServiceMessenger ;
201
- webSocketService : WebSocketService ;
202
238
} ,
203
239
) {
204
240
this . #messenger = options . messenger ;
205
- this . #webSocketService = options . webSocketService ;
206
241
207
242
// Set configuration with defaults
208
243
this . #options = {
@@ -228,21 +263,21 @@ export class AccountActivityService {
228
263
*/
229
264
async subscribeAccounts ( subscription : AccountSubscription ) : Promise < void > {
230
265
try {
231
- await this . #webSocketService . connect ( ) ;
266
+ await this . #messenger . call ( 'BackendWebSocketService:connect' ) ;
232
267
233
268
// Create channel name from address
234
269
const channel = `${ this . #options. subscriptionNamespace } .${ subscription . address } ` ;
235
270
236
271
// Check if already subscribed
237
- if ( this . #webSocketService . isChannelSubscribed ( channel ) ) {
272
+ if ( this . #messenger . call ( 'BackendWebSocketService:isChannelSubscribed' , channel ) ) {
238
273
console . log ( `[${ SERVICE_NAME } ] Already subscribed to channel: ${ channel } ` ) ;
239
274
return ;
240
275
}
241
276
242
277
// Set up system notifications callback for chain status updates
243
278
const systemChannelName = `system-notifications.v1.${ this . #options. subscriptionNamespace } ` ;
244
279
console . log ( `[${ SERVICE_NAME } ] Adding channel callback for '${ systemChannelName } '` ) ;
245
- this . #webSocketService . addChannelCallback ( {
280
+ this . #messenger . call ( 'BackendWebSocketService:addChannelCallback' , {
246
281
channelName : systemChannelName ,
247
282
callback : ( notification ) => {
248
283
try {
@@ -255,9 +290,26 @@ export class AccountActivityService {
255
290
}
256
291
} ) ;
257
292
258
- // Create subscription with optimized callback routing
259
- await this . #webSocketService. subscribe ( {
260
- channels : [ channel ] ,
293
+ // Create subscription using sendRequest since subscribe isn't exposed as messenger action
294
+ const subscriptionResponse = await this . #messenger. call ( 'BackendWebSocketService:sendRequest' , {
295
+ event : 'subscribe' ,
296
+ data : { channels : [ channel ] } ,
297
+ } ) ;
298
+
299
+ if ( ! subscriptionResponse ?. subscriptionId ) {
300
+ throw new Error ( 'Invalid subscription response: missing subscription ID' ) ;
301
+ }
302
+
303
+ // Check for failures
304
+ if ( subscriptionResponse . failed && subscriptionResponse . failed . length > 0 ) {
305
+ throw new Error (
306
+ `Subscription failed for channels: ${ subscriptionResponse . failed . join ( ', ' ) } ` ,
307
+ ) ;
308
+ }
309
+
310
+ // Set up channel callback for direct processing of account activity updates
311
+ this . #messenger. call ( 'BackendWebSocketService:addChannelCallback' , {
312
+ channelName : channel ,
261
313
callback : ( notification ) => {
262
314
// Fast path: Direct processing of account activity updates
263
315
this . #handleAccountActivityUpdate(
@@ -283,7 +335,7 @@ export class AccountActivityService {
283
335
// Find channel for the specified address
284
336
const channel = `${ this . #options. subscriptionNamespace } .${ address } ` ;
285
337
const subscriptionInfo =
286
- this . #webSocketService . getSubscriptionByChannel ( channel ) ;
338
+ this . #messenger . call ( 'BackendWebSocketService:getSubscriptionByChannel' , channel ) ;
287
339
288
340
if ( ! subscriptionInfo ) {
289
341
console . log ( `[${ SERVICE_NAME } ] No subscription found for address: ${ address } ` ) ;
@@ -429,7 +481,7 @@ export class AccountActivityService {
429
481
const newChannel = `${ this . #options. subscriptionNamespace } .${ newAddress } ` ;
430
482
431
483
// If already subscribed to this account, no need to change
432
- if ( this . #webSocketService . isChannelSubscribed ( newChannel ) ) {
484
+ if ( this . #messenger . call ( 'BackendWebSocketService:isChannelSubscribed' , newChannel ) ) {
433
485
console . log ( `[${ SERVICE_NAME } ] Already subscribed to account: ${ newAddress } ` ) ;
434
486
return ;
435
487
}
@@ -467,8 +519,8 @@ export class AccountActivityService {
467
519
468
520
// All subscriptions will be cleaned up automatically on WebSocket disconnect
469
521
470
- await this . #webSocketService . disconnect ( ) ;
471
- await this . #webSocketService . connect ( ) ;
522
+ await this . #messenger . call ( 'BackendWebSocketService:disconnect' ) ;
523
+ await this . #messenger . call ( 'BackendWebSocketService:connect' ) ;
472
524
} catch ( error ) {
473
525
console . error ( `[${ SERVICE_NAME } ] Failed to force WebSocket reconnection:` , error ) ;
474
526
}
@@ -537,7 +589,7 @@ export class AccountActivityService {
537
589
const channel = `${ this . #options. subscriptionNamespace } .${ address } ` ;
538
590
539
591
// Only subscribe if we're not already subscribed to this account
540
- if ( ! this . #webSocketService . isChannelSubscribed ( channel ) ) {
592
+ if ( ! this . #messenger . call ( 'BackendWebSocketService:isChannelSubscribed' , channel ) ) {
541
593
await this . subscribeAccounts ( { address } ) ;
542
594
console . log ( `[${ SERVICE_NAME } ] Successfully subscribed to selected account: ${ address } ` ) ;
543
595
} else {
@@ -558,7 +610,7 @@ export class AccountActivityService {
558
610
console . log ( `[${ SERVICE_NAME } ] Unsubscribing from all account activity subscriptions...` ) ;
559
611
560
612
// Use WebSocketService to find all subscriptions with our namespace prefix
561
- const accountActivitySubscriptions = this . #webSocketService . findSubscriptionsByChannelPrefix (
613
+ const accountActivitySubscriptions = this . #messenger . call ( 'BackendWebSocketService:findSubscriptionsByChannelPrefix' ,
562
614
this . #options. subscriptionNamespace
563
615
) ;
564
616
@@ -617,7 +669,7 @@ export class AccountActivityService {
617
669
// We don't need to manually unsubscribe here for fast cleanup
618
670
619
671
// Clean up system notification callback
620
- this . #webSocketService . removeChannelCallback ( `system-notifications.v1.${ this . #options. subscriptionNamespace } ` ) ;
672
+ this . #messenger . call ( 'BackendWebSocketService:removeChannelCallback' , `system-notifications.v1.${ this . #options. subscriptionNamespace } ` ) ;
621
673
622
674
// Unregister action handlers to prevent stale references
623
675
this . #messenger. unregisterActionHandler (
0 commit comments