Skip to content

Commit 41eade6

Browse files
committed
Merge remote-tracking branch 'origin/main' into feat/atomic-batch-transactions
2 parents 76f4447 + 97e2028 commit 41eade6

File tree

55 files changed

+1159
-612
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1159
-612
lines changed

.yarnrc.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,12 @@ npmAuditIgnoreAdvisories:
126126
# New package name format for new versions: @ethereumjs/wallet.
127127
- 'ethereumjs-wallet (deprecation)'
128128

129+
# The new trezor version breaks the webpack build due to issues with ESM and CommonJS
130+
# Leading to this error on start: `Uncaught ReferenceError: exports is not defined`
131+
# We temporarily ignore the audit failure until we can safely upgrade to the new version without breaking the webpack build
132+
# Check Trezor 9.5.X Changelog for more info: https://github.com/trezor/trezor-suite/blob/develop/packages/connect/CHANGELOG.md
133+
- '@trezor/connect-web (deprecation)'
134+
129135
plugins:
130136
- path: .yarn/plugins/@yarnpkg/plugin-allow-scripts.cjs
131137
spec: 'https://raw.githubusercontent.com/LavaMoat/LavaMoat/main/packages/yarn-plugin-allow-scripts/bundles/@yarnpkg/plugin-allow-scripts.js'

app/_locales/en/messages.json

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/_locales/en_GB/messages.json

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/scripts/controller-init/controller-list.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import {
3030
RateLimitController,
3131
RateLimitedApiMap,
3232
} from '@metamask/rate-limit-controller';
33+
import { Controller as AuthenticationController } from '@metamask/profile-sync-controller/auth';
34+
import { Controller as UserStorageController } from '@metamask/profile-sync-controller/user-storage';
3335
import OnboardingController from '../controllers/onboarding';
3436
import { PreferencesController } from '../controllers/preferences-controller';
3537
import SwapsController from '../controllers/swaps';
@@ -38,6 +40,7 @@ import SwapsController from '../controllers/swaps';
3840
* Union of all controllers supporting or required by modular initialization.
3941
*/
4042
export type Controller =
43+
| AuthenticationController
4144
| CronjobController
4245
| ExecutionService
4346
| GasFeeController
@@ -65,13 +68,15 @@ export type Controller =
6568
| (TransactionUpdateController & {
6669
name: 'TransactionUpdateController';
6770
state: Record<string, unknown>;
68-
});
71+
})
72+
| UserStorageController;
6973

7074
/**
7175
* Flat state object for all controllers supporting or required by modular initialization.
7276
* e.g. `{ transactions: [] }`.
7377
*/
7478
export type ControllerFlatState = AccountsController['state'] &
79+
AuthenticationController['state'] &
7580
CronjobController['state'] &
7681
GasFeeController['state'] &
7782
JsonSnapsRegistry['state'] &
@@ -94,4 +99,5 @@ export type ControllerFlatState = AccountsController['state'] &
9499
SnapInsightsController['state'] &
95100
SnapInterfaceController['state'] &
96101
TransactionController['state'] &
97-
SwapsController['state'];
102+
SwapsController['state'] &
103+
UserStorageController['state'];
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { Controller as AuthenticationController } from '@metamask/profile-sync-controller/auth';
2+
import { Messenger } from '@metamask/base-controller';
3+
import { buildControllerInitRequestMock } from '../test/utils';
4+
import { ControllerInitRequest } from '../types';
5+
import {
6+
getAuthenticationControllerMessenger,
7+
AuthenticationControllerMessenger,
8+
} from '../messengers/identity';
9+
import { AuthenticationControllerInit } from './authentication-controller-init';
10+
11+
jest.mock('@metamask/profile-sync-controller/auth');
12+
13+
function buildInitRequestMock(): jest.Mocked<
14+
ControllerInitRequest<AuthenticationControllerMessenger>
15+
> {
16+
const baseControllerMessenger = new Messenger();
17+
18+
return {
19+
...buildControllerInitRequestMock(),
20+
controllerMessenger: getAuthenticationControllerMessenger(
21+
baseControllerMessenger,
22+
),
23+
initMessenger: undefined,
24+
};
25+
}
26+
27+
describe('AuthenticationControllerInit', () => {
28+
const AuthenticationControllerClassMock = jest.mocked(
29+
AuthenticationController,
30+
);
31+
32+
beforeEach(() => {
33+
jest.resetAllMocks();
34+
});
35+
36+
it('returns controller instance', () => {
37+
const requestMock = buildInitRequestMock();
38+
expect(AuthenticationControllerInit(requestMock).controller).toBeInstanceOf(
39+
AuthenticationController,
40+
);
41+
});
42+
43+
it('initializes with correct messenger and state', () => {
44+
const requestMock = buildInitRequestMock();
45+
AuthenticationControllerInit(requestMock);
46+
47+
expect(AuthenticationControllerClassMock).toHaveBeenCalledWith({
48+
messenger: requestMock.controllerMessenger,
49+
state: requestMock.persistedState.AuthenticationController,
50+
metametrics: {
51+
getMetaMetricsId: requestMock.getMetaMetricsId,
52+
agent: 'extension',
53+
},
54+
});
55+
});
56+
});
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import {
2+
AuthenticationControllerState,
3+
Controller as AuthenticationController,
4+
} from '@metamask/profile-sync-controller/auth';
5+
import { ControllerInitFunction } from '../types';
6+
import { AuthenticationControllerMessenger } from '../messengers/identity';
7+
8+
/**
9+
* Initialize the Authentication controller.
10+
*
11+
* @param request - The request object.
12+
* @param request.controllerMessenger - The messenger to use for the controller.
13+
* @param request.persistedState - The persisted state of the extension.
14+
* @param request.getMetaMetricsId
15+
* @returns The initialized controller.
16+
*/
17+
export const AuthenticationControllerInit: ControllerInitFunction<
18+
AuthenticationController,
19+
AuthenticationControllerMessenger
20+
> = ({ controllerMessenger, persistedState, getMetaMetricsId }) => {
21+
const controller = new AuthenticationController({
22+
messenger: controllerMessenger,
23+
state:
24+
persistedState.AuthenticationController as AuthenticationControllerState,
25+
metametrics: {
26+
getMetaMetricsId,
27+
agent: 'extension',
28+
},
29+
});
30+
31+
return {
32+
controller,
33+
};
34+
};
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { Controller as UserStorageController } from '@metamask/profile-sync-controller/user-storage';
2+
import { Messenger } from '@metamask/base-controller';
3+
import { buildControllerInitRequestMock } from '../test/utils';
4+
import { ControllerInitRequest } from '../types';
5+
import {
6+
getUserStorageControllerMessenger,
7+
UserStorageControllerMessenger,
8+
} from '../messengers/identity';
9+
import { UserStorageControllerInit } from './user-storage-controller-init';
10+
11+
jest.mock('@metamask/profile-sync-controller/user-storage');
12+
jest.mock('../../../../shared/modules/mv3.utils', () => ({
13+
isManifestV3: true,
14+
}));
15+
jest.mock('../../../../shared/modules/environment', () => ({
16+
isProduction: () => false,
17+
}));
18+
19+
function buildInitRequestMock(): jest.Mocked<
20+
ControllerInitRequest<UserStorageControllerMessenger>
21+
> {
22+
const baseControllerMessenger = new Messenger();
23+
24+
return {
25+
...buildControllerInitRequestMock(),
26+
controllerMessenger: getUserStorageControllerMessenger(
27+
baseControllerMessenger,
28+
),
29+
initMessenger: undefined,
30+
};
31+
}
32+
33+
describe('UserStorageControllerInit', () => {
34+
const UserStorageControllerClassMock = jest.mocked(UserStorageController);
35+
36+
beforeEach(() => {
37+
jest.resetAllMocks();
38+
});
39+
40+
it('returns controller instance', () => {
41+
const requestMock = buildInitRequestMock();
42+
expect(UserStorageControllerInit(requestMock).controller).toBeInstanceOf(
43+
UserStorageController,
44+
);
45+
});
46+
47+
it('initializes with correct messenger and state', () => {
48+
const requestMock = buildInitRequestMock();
49+
UserStorageControllerInit(requestMock);
50+
51+
expect(UserStorageControllerClassMock).toHaveBeenCalledWith({
52+
messenger: requestMock.controllerMessenger,
53+
state: requestMock.persistedState.UserStorageController,
54+
config: {
55+
accountSyncing: {
56+
maxNumberOfAccountsToAdd: 100,
57+
onAccountAdded: expect.any(Function),
58+
onAccountNameUpdated: expect.any(Function),
59+
onAccountSyncErroneousSituation: expect.any(Function),
60+
},
61+
},
62+
env: {
63+
isAccountSyncingEnabled: true,
64+
},
65+
});
66+
});
67+
});
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import {
2+
UserStorageControllerMessenger,
3+
UserStorageControllerState,
4+
Controller as UserStorageController,
5+
} from '@metamask/profile-sync-controller/user-storage';
6+
import { captureException } from '@sentry/browser';
7+
import { ControllerInitFunction } from '../types';
8+
import { isProduction } from '../../../../shared/modules/environment';
9+
import {
10+
MetaMetricsEventCategory,
11+
MetaMetricsEventName,
12+
} from '../../../../shared/constants/metametrics';
13+
import { isManifestV3 } from '../../../../shared/modules/mv3.utils';
14+
15+
/**
16+
* Initialize the UserStorage controller.
17+
*
18+
* @param request - The request object.
19+
* @param request.controllerMessenger - The messenger to use for the controller.
20+
* @param request.persistedState - The persisted state of the extension.
21+
* @returns The initialized controller.
22+
*/
23+
export const UserStorageControllerInit: ControllerInitFunction<
24+
UserStorageController,
25+
UserStorageControllerMessenger
26+
> = (request) => {
27+
const { controllerMessenger, persistedState, trackEvent } = request;
28+
const controller = new UserStorageController({
29+
messenger: controllerMessenger,
30+
state: persistedState.UserStorageController as UserStorageControllerState,
31+
config: {
32+
accountSyncing: {
33+
maxNumberOfAccountsToAdd: isProduction() ? undefined : 100,
34+
onAccountAdded: (profileId) => {
35+
trackEvent({
36+
category: MetaMetricsEventCategory.ProfileSyncing,
37+
event: MetaMetricsEventName.AccountsSyncAdded,
38+
properties: {
39+
profile_id: profileId,
40+
},
41+
});
42+
},
43+
onAccountNameUpdated: (profileId) => {
44+
trackEvent({
45+
category: MetaMetricsEventCategory.ProfileSyncing,
46+
event: MetaMetricsEventName.AccountsSyncNameUpdated,
47+
properties: {
48+
profile_id: profileId,
49+
},
50+
});
51+
},
52+
onAccountSyncErroneousSituation: (
53+
profileId,
54+
situationMessage,
55+
sentryContext,
56+
) => {
57+
captureException(
58+
new Error(`Account sync - ${situationMessage}`),
59+
sentryContext,
60+
);
61+
trackEvent({
62+
category: MetaMetricsEventCategory.ProfileSyncing,
63+
event: MetaMetricsEventName.AccountsSyncErroneousSituation,
64+
properties: {
65+
profile_id: profileId,
66+
situation_message: situationMessage,
67+
},
68+
});
69+
},
70+
},
71+
},
72+
env: {
73+
isAccountSyncingEnabled: isManifestV3,
74+
},
75+
});
76+
77+
return {
78+
controller,
79+
};
80+
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { Messenger, RestrictedMessenger } from '@metamask/base-controller';
2+
import { getAuthenticationControllerMessenger } from './authentication-controller-messenger';
3+
4+
describe('getAuthenticationControllerMessenger', () => {
5+
it('returns a restricted messenger', () => {
6+
const messenger = new Messenger<never, never>();
7+
const authenticationControllerMessenger =
8+
getAuthenticationControllerMessenger(messenger);
9+
10+
expect(authenticationControllerMessenger).toBeInstanceOf(
11+
RestrictedMessenger,
12+
);
13+
});
14+
});
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { Messenger } from '@metamask/base-controller';
2+
import {
3+
KeyringControllerGetStateAction,
4+
KeyringControllerLockEvent,
5+
KeyringControllerUnlockEvent,
6+
} from '@metamask/keyring-controller';
7+
import { HandleSnapRequest } from '@metamask/snaps-controllers';
8+
9+
type MessengerActions = KeyringControllerGetStateAction | HandleSnapRequest;
10+
11+
type MessengerEvents =
12+
| KeyringControllerLockEvent
13+
| KeyringControllerUnlockEvent;
14+
15+
export type AuthenticationControllerMessenger = ReturnType<
16+
typeof getAuthenticationControllerMessenger
17+
>;
18+
19+
/**
20+
* Get a restricted messenger for the Authentication controller. This is scoped to the
21+
* actions and events that the Authentication controller is allowed to handle.
22+
*
23+
* @param messenger - The messenger to restrict.
24+
* @returns The restricted messenger.
25+
*/
26+
export function getAuthenticationControllerMessenger(
27+
messenger: Messenger<MessengerActions, MessengerEvents>,
28+
) {
29+
return messenger.getRestricted({
30+
name: 'AuthenticationController',
31+
allowedActions: [
32+
'KeyringController:getState',
33+
'SnapController:handleRequest',
34+
],
35+
allowedEvents: ['KeyringController:lock', 'KeyringController:unlock'],
36+
});
37+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export { getAuthenticationControllerMessenger } from './authentication-controller-messenger';
2+
export type { AuthenticationControllerMessenger } from './authentication-controller-messenger';
3+
4+
export { getUserStorageControllerMessenger } from './user-storage-controller-messenger';
5+
export type { UserStorageControllerMessenger } from './user-storage-controller-messenger';

0 commit comments

Comments
 (0)