Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,8 @@ linkStyle default opacity:0.5
chain_agnostic_permission --> permission_controller;
composable_controller --> base_controller;
composable_controller --> json_rpc_engine;
core_backend --> base_controller;
core_backend --> controller_utils;
core_backend --> messenger;
core_backend --> profile_sync_controller;
core_backend --> accounts_controller;
core_backend --> keyring_controller;
Expand All @@ -216,6 +216,7 @@ linkStyle default opacity:0.5
earn_controller --> transaction_controller;
eip_5792_middleware --> transaction_controller;
eip_5792_middleware --> keyring_controller;
eip_7702_internal_rpc_middleware --> controller_utils;
eip1193_permission_middleware --> chain_agnostic_permission;
eip1193_permission_middleware --> controller_utils;
eip1193_permission_middleware --> json_rpc_engine;
Expand Down
10 changes: 10 additions & 0 deletions packages/core-backend/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6823](https://github.com/MetaMask/core/pull/6823))
- Previously, `AccountActivityService` and `BackendWebSocketService` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`.
- **BREAKING:** Metadata property `anonymous` renamed to `includeInDebugSnapshot` ([#6823](https://github.com/MetaMask/core/pull/6823))

### Removed

- **BREAKING:** Remove exported type aliases and constants that were specific to controller messenger integration ([#6823](https://github.com/MetaMask/core/pull/6823))
- Removed type exports: `BackendWebSocketServiceAllowedActions`, `BackendWebSocketServiceAllowedEvents`, `AccountActivityServiceAllowedActions`, `AccountActivityServiceAllowedEvents`
- Removed constant exports: `ACCOUNT_ACTIVITY_SERVICE_ALLOWED_ACTIONS`, `ACCOUNT_ACTIVITY_SERVICE_ALLOWED_EVENTS`
- These types and constants were internal implementation details that should not have been exposed. Consumers should use the service-specific messenger types directly.
- Bump `@metamask/profile-sync-controller` from `^25.1.1` to `^25.1.2` ([#6940](https://github.com/MetaMask/core/pull/6940))

## [3.0.0]
Expand Down
2 changes: 1 addition & 1 deletion packages/core-backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@
"test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch"
},
"dependencies": {
"@metamask/base-controller": "^8.4.2",
"@metamask/controller-utils": "^11.14.1",
"@metamask/messenger": "^0.3.0",
"@metamask/profile-sync-controller": "^25.1.2",
"@metamask/utils": "^11.8.1",
"uuid": "^8.3.2"
Expand Down
112 changes: 83 additions & 29 deletions packages/core-backend/src/AccountActivityService.test.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,36 @@
import { Messenger } from '@metamask/base-controller';
import type { InternalAccount } from '@metamask/keyring-internal-api';
import {
Messenger,
MOCK_ANY_NAMESPACE,
type MessengerActions,
type MessengerEvents,
type MockAnyNamespace,
} from '@metamask/messenger';
import type { Hex } from '@metamask/utils';

import type {
AccountActivityServiceAllowedEvents,
AccountActivityServiceAllowedActions,
} from './AccountActivityService';
import {
AccountActivityService,
type AccountActivityServiceMessenger,
type SubscriptionOptions,
ACCOUNT_ACTIVITY_SERVICE_ALLOWED_ACTIONS,
ACCOUNT_ACTIVITY_SERVICE_ALLOWED_EVENTS,
} from './AccountActivityService';
import type { ServerNotificationMessage } from './BackendWebSocketService';
import { WebSocketState } from './BackendWebSocketService';
import type { Transaction, BalanceUpdate } from './types';
import type { AccountActivityMessage } from './types';
import { flushPromises } from '../../../tests/helpers';

type AllAccountActivityServiceActions =
MessengerActions<AccountActivityServiceMessenger>;

type AllAccountActivityServiceEvents =
MessengerEvents<AccountActivityServiceMessenger>;

type RootMessenger = Messenger<
MockAnyNamespace,
AllAccountActivityServiceActions,
AllAccountActivityServiceEvents
>;

// Helper function for completing async operations
const completeAsyncOperations = async (timeoutMs = 0) => {
await flushPromises();
Expand Down Expand Up @@ -48,25 +60,70 @@ const createMockInternalAccount = (options: {
scopes: ['eip155:1'], // Required scopes property
});

/**
* Creates and returns a root messenger for testing
*
* @returns A messenger instance
*/
function getRootMessenger(): RootMessenger {
return new Messenger({
namespace: MOCK_ANY_NAMESPACE,
});
}

/**
* Creates a real messenger with registered mock actions for testing
* Each call creates a completely independent messenger to ensure test isolation
*
* @returns Object containing the messenger and mock action functions
*/
const getMessenger = () => {
const getMessenger = (): {
rootMessenger: RootMessenger;
messenger: AccountActivityServiceMessenger;
mocks: {
getSelectedAccount: jest.Mock;
connect: jest.Mock;
subscribe: jest.Mock;
channelHasSubscription: jest.Mock;
getSubscriptionsByChannel: jest.Mock;
findSubscriptionsByChannelPrefix: jest.Mock;
forceReconnection: jest.Mock;
addChannelCallback: jest.Mock;
removeChannelCallback: jest.Mock;
};
} => {
// Use any types for the root messenger to avoid complex type constraints in tests
// Create a unique root messenger for each test
const rootMessenger = new Messenger<
AccountActivityServiceAllowedActions,
AccountActivityServiceAllowedEvents
>();
const messenger: AccountActivityServiceMessenger =
rootMessenger.getRestricted({
name: 'AccountActivityService',
allowedActions: [...ACCOUNT_ACTIVITY_SERVICE_ALLOWED_ACTIONS],
allowedEvents: [...ACCOUNT_ACTIVITY_SERVICE_ALLOWED_EVENTS],
});
const rootMessenger = getRootMessenger();
const messenger: AccountActivityServiceMessenger = new Messenger<
'AccountActivityService',
AllAccountActivityServiceActions,
AllAccountActivityServiceEvents,
RootMessenger
>({
namespace: 'AccountActivityService',
parent: rootMessenger,
});

rootMessenger.delegate({
actions: [
'AccountsController:getSelectedAccount',
'BackendWebSocketService:connect',
'BackendWebSocketService:forceReconnection',
'BackendWebSocketService:subscribe',
'BackendWebSocketService:getConnectionInfo',
'BackendWebSocketService:channelHasSubscription',
'BackendWebSocketService:getSubscriptionsByChannel',
'BackendWebSocketService:findSubscriptionsByChannelPrefix',
'BackendWebSocketService:addChannelCallback',
'BackendWebSocketService:removeChannelCallback',
],
events: [
'AccountsController:selectedAccountChange',
'BackendWebSocketService:connectionStateChanged',
],
messenger,
});

// Create mock action handlers
const mockGetSelectedAccount = jest.fn();
Expand Down Expand Up @@ -215,10 +272,7 @@ type WithServiceOptions = {
type WithServiceCallback<ReturnValue> = (payload: {
service: AccountActivityService;
messenger: AccountActivityServiceMessenger;
rootMessenger: Messenger<
AccountActivityServiceAllowedActions,
AccountActivityServiceAllowedEvents
>;
rootMessenger: RootMessenger;
mocks: {
getSelectedAccount: jest.Mock;
connect: jest.Mock;
Expand Down Expand Up @@ -633,7 +687,7 @@ describe('AccountActivityService', () => {
});

// Publish WebSocket ERROR state event - should flush tracked chains as down
await rootMessenger.publish(
rootMessenger.publish(
'BackendWebSocketService:connectionStateChanged',
{
state: WebSocketState.ERROR,
Expand Down Expand Up @@ -667,7 +721,7 @@ describe('AccountActivityService', () => {
mocks.getSelectedAccount.mockReturnValue(null);

// Publish WebSocket ERROR state event without any tracked chains
await rootMessenger.publish(
rootMessenger.publish(
'BackendWebSocketService:connectionStateChanged',
{
state: WebSocketState.ERROR,
Expand Down Expand Up @@ -718,7 +772,7 @@ describe('AccountActivityService', () => {
});

// Publish account change event - will be picked up by controller subscription
await rootMessenger.publish(
rootMessenger.publish(
'AccountsController:selectedAccountChange',
solanaAccount,
);
Expand Down Expand Up @@ -748,7 +802,7 @@ describe('AccountActivityService', () => {
});

// Publish account change event - will be picked up by controller subscription
await rootMessenger.publish(
rootMessenger.publish(
'AccountsController:selectedAccountChange',
unknownAccount,
);
Expand All @@ -770,7 +824,7 @@ describe('AccountActivityService', () => {
mocks.getSelectedAccount.mockReturnValue(null);

// Publish WebSocket connection event - will be picked up by controller subscription
await rootMessenger.publish(
rootMessenger.publish(
'BackendWebSocketService:connectionStateChanged',
{
state: WebSocketState.CONNECTED,
Expand Down Expand Up @@ -810,7 +864,7 @@ describe('AccountActivityService', () => {
});

// Publish account change event on root messenger
await rootMessenger.publish(
rootMessenger.publish(
'AccountsController:selectedAccountChange',
newAccount,
);
Expand Down Expand Up @@ -848,7 +902,7 @@ describe('AccountActivityService', () => {
});

// Publish account change event on root messenger
await rootMessenger.publish(
rootMessenger.publish(
'AccountsController:selectedAccountChange',
newAccount,
);
Expand Down
14 changes: 6 additions & 8 deletions packages/core-backend/src/AccountActivityService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import type {
AccountsControllerGetSelectedAccountAction,
AccountsControllerSelectedAccountChangeEvent,
} from '@metamask/accounts-controller';
import type { RestrictedMessenger } from '@metamask/base-controller';
import type { TraceCallback } from '@metamask/controller-utils';
import type { InternalAccount } from '@metamask/keyring-internal-api';
import type { Messenger } from '@metamask/messenger';

import type { AccountActivityServiceMethodActions } from './AccountActivityService-method-action-types';
import type {
Expand Down Expand Up @@ -96,7 +96,7 @@ export const ACCOUNT_ACTIVITY_SERVICE_ALLOWED_EVENTS = [
'BackendWebSocketService:connectionStateChanged',
] as const;

export type AccountActivityServiceAllowedActions =
export type AllowedActions =
| AccountsControllerGetSelectedAccountAction
| BackendWebSocketServiceMethodActions;

Expand Down Expand Up @@ -134,16 +134,14 @@ export type AccountActivityServiceEvents =
| AccountActivityServiceSubscriptionErrorEvent
| AccountActivityServiceStatusChangedEvent;

export type AccountActivityServiceAllowedEvents =
export type AllowedEvents =
| AccountsControllerSelectedAccountChangeEvent
| BackendWebSocketServiceConnectionStateChangedEvent;

export type AccountActivityServiceMessenger = RestrictedMessenger<
export type AccountActivityServiceMessenger = Messenger<
typeof SERVICE_NAME,
AccountActivityServiceActions | AccountActivityServiceAllowedActions,
AccountActivityServiceEvents | AccountActivityServiceAllowedEvents,
AccountActivityServiceAllowedActions['type'],
AccountActivityServiceAllowedEvents['type']
AccountActivityServiceActions | AllowedActions,
AccountActivityServiceEvents | AllowedEvents
>;

// =============================================================================
Expand Down
Loading
Loading