Skip to content

Commit 4cd9527

Browse files
Merge branch 'main' into fix/update-focus-outline-menu-item
2 parents cb9d34e + b57ed09 commit 4cd9527

32 files changed

+1937
-542
lines changed

.circleci/config.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ version: 2.1
33
executors:
44
node-browsers-small:
55
docker:
6-
- image: cimg/node:20.18-browsers
6+
- image: cimg/node:22.13-browsers
77
resource_class: small
88
environment:
99
NODE_OPTIONS: --max_old_space_size=2048
1010
node-browsers-medium:
1111
docker:
12-
- image: cimg/node:20.18-browsers
12+
- image: cimg/node:22.13-browsers
1313
resource_class: medium
1414
environment:
1515
NODE_OPTIONS: --max_old_space_size=3072
@@ -21,7 +21,7 @@ executors:
2121
NODE_OPTIONS: --max_old_space_size=6144
2222
node-browsers-medium-plus:
2323
docker:
24-
- image: cimg/node:20.18-browsers
24+
- image: cimg/node:22.13-browsers
2525
resource_class: medium+
2626
environment:
2727
NODE_OPTIONS: --max_old_space_size=4096

.depcheckrc.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ ignores:
2424
- '@metamask/phishing-warning' # statically hosted as part of some e2e tests
2525
- '@metamask/test-dapp'
2626
- '@metamask/design-tokens' # Only imported in index.css
27-
- '@tsconfig/node20' # required dynamically by TS, used in tsconfig.json
27+
- '@tsconfig/node22' # required dynamically by TS, used in tsconfig.json
2828
- '@sentry/cli' # invoked as `sentry-cli`
2929
- 'chromedriver'
3030
- 'depcheck' # ooo meta

.github/CODEOWNERS

+7-6
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,13 @@ privacy-snapshot.json @MetaMask/extension-privacy-reviewers
5656
.devcontainer/ @MetaMask/extension-security-team @HowardBraham
5757

5858
# Confirmations team to own code for confirmations on UI.
59-
app/scripts/lib/ppom @MetaMask/confirmations
60-
app/scripts/lib/signature @MetaMask/confirmations
61-
app/scripts/lib/transaction/decode @MetaMask/confirmations
62-
app/scripts/lib/transaction/metrics.* @MetaMask/confirmations
63-
app/scripts/lib/transaction/util.* @MetaMask/confirmations
64-
ui/pages/confirmations @MetaMask/confirmations
59+
app/scripts/controller-init/confirmations @MetaMask/confirmations
60+
app/scripts/lib/ppom @MetaMask/confirmations
61+
app/scripts/lib/signature @MetaMask/confirmations
62+
app/scripts/lib/transaction/decode @MetaMask/confirmations
63+
app/scripts/lib/transaction/metrics.* @MetaMask/confirmations
64+
app/scripts/lib/transaction/util.* @MetaMask/confirmations
65+
ui/pages/confirmations @MetaMask/confirmations
6566

6667
# Design System to own code for the component-library folder
6768
# Slack handle: @metamask-design-system-team | Slack channel: #metamask-design-system

.github/workflows/publish-prerelease.yml

+3-2
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ jobs:
2222
- name: Get merge base commit hash
2323
id: get-merge-base
2424
env:
25-
BASE_REF: ${{ github.event.pull_request.base.ref }}
25+
BASE_SHA: ${{ github.event.pull_request.base.sha }}
26+
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
2627
run: |
27-
merge_base="$(git merge-base "origin/${BASE_REF}" HEAD)"
28+
merge_base="$(git merge-base "${BASE_SHA}" "${HEAD_SHA}")"
2829
echo "MERGE_BASE=${merge_base}" >> "$GITHUB_OUTPUT"
2930
echo "Merge base is '${merge_base}'"
3031

.nvmrc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v20.18
1+
v22.13

app/scripts/background.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -1045,12 +1045,12 @@ export function setupController(
10451045
//
10461046
updateBadge();
10471047

1048-
controller.decryptMessageController.hub.on(
1049-
METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE,
1048+
controller.controllerMessenger.subscribe(
1049+
METAMASK_CONTROLLER_EVENTS.DECRYPT_MESSAGE_MANAGER_UPDATE_BADGE,
10501050
updateBadge,
10511051
);
1052-
controller.encryptionPublicKeyController.hub.on(
1053-
METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE,
1052+
controller.controllerMessenger.subscribe(
1053+
METAMASK_CONTROLLER_EVENTS.ENCRYPTION_PUBLIC_KEY_MANAGER_UPDATE_BADGE,
10541054
updateBadge,
10551055
);
10561056
controller.signatureController.hub.on(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import {
2+
PPOMController,
3+
PPOMControllerMessenger,
4+
} from '@metamask/ppom-validator';
5+
import { ControllerMessenger } from '@metamask/base-controller';
6+
import { PreferencesController } from '../../controllers/preferences-controller';
7+
import { buildControllerInitRequestMock, CHAIN_ID_MOCK } from '../test/utils';
8+
import { ControllerInitRequest } from '../types';
9+
import {
10+
getPPOMControllerInitMessenger,
11+
getPPOMControllerMessenger,
12+
PPOMControllerInitMessenger,
13+
} from '../messengers/ppom-controller-messenger';
14+
import { PPOMControllerInit } from './ppom-controller-init';
15+
16+
type PPOMControllerOptions = ConstructorParameters<typeof PPOMController>[0];
17+
18+
jest.mock('@metamask/ppom-validator');
19+
20+
/**
21+
* Build a mock PreferencesController.
22+
*
23+
* @param partialMock - A partial mock object for the PreferencesController, merged
24+
* with the default mock.
25+
* @returns A mock PreferencesController.
26+
*/
27+
function buildControllerMock(
28+
partialMock?: Partial<PreferencesController>,
29+
): PreferencesController {
30+
const defaultPreferencesControllerMock = {
31+
state: { securityAlertsEnabled: true },
32+
};
33+
34+
// @ts-expect-error Incomplete mock, just includes properties used by code-under-test.
35+
return {
36+
...defaultPreferencesControllerMock,
37+
...partialMock,
38+
};
39+
}
40+
41+
function buildInitRequestMock(): jest.Mocked<
42+
ControllerInitRequest<PPOMControllerMessenger, PPOMControllerInitMessenger>
43+
> {
44+
const baseControllerMessenger = new ControllerMessenger();
45+
46+
const requestMock = {
47+
...buildControllerInitRequestMock(),
48+
controllerMessenger: getPPOMControllerMessenger(baseControllerMessenger),
49+
initMessenger: getPPOMControllerInitMessenger(baseControllerMessenger),
50+
};
51+
52+
requestMock.getController.mockReturnValue(buildControllerMock());
53+
54+
return requestMock;
55+
}
56+
57+
describe('PPOM Controller Init', () => {
58+
const ppomControllerClassMock = jest.mocked(PPOMController);
59+
60+
/**
61+
* Extract a constructor option passed to the controller.
62+
*
63+
* @param option - The option to extract.
64+
* @param dependencyProperties - Any properties required on the controller dependencies.
65+
* @returns The extracted option.
66+
*/
67+
function testConstructorOption<T extends keyof PPOMControllerOptions>(
68+
option: T,
69+
dependencyProperties?: Record<string, unknown>,
70+
): PPOMControllerOptions[T] {
71+
const requestMock = buildInitRequestMock();
72+
73+
requestMock.getController.mockReturnValue(
74+
buildControllerMock(dependencyProperties),
75+
);
76+
77+
PPOMControllerInit(requestMock);
78+
79+
return ppomControllerClassMock.mock.calls[0][0][option];
80+
}
81+
82+
beforeEach(() => {
83+
jest.resetAllMocks();
84+
});
85+
86+
it('returns controller instance', () => {
87+
const requestMock = buildInitRequestMock();
88+
expect(PPOMControllerInit(requestMock).controller).toBeInstanceOf(
89+
PPOMController,
90+
);
91+
});
92+
93+
it('determines if security alerts enabled using preference', () => {
94+
const securityAlertsEnabled = testConstructorOption(
95+
'securityAlertsEnabled',
96+
{ state: { securityAlertsEnabled: true } },
97+
);
98+
99+
expect(securityAlertsEnabled).toBe(true);
100+
});
101+
102+
it('sets chain ID to global chain ID', () => {
103+
const chainId = testConstructorOption('chainId');
104+
expect(chainId).toBe(CHAIN_ID_MOCK);
105+
});
106+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import {
2+
PPOMController,
3+
PPOMControllerMessenger,
4+
} from '@metamask/ppom-validator';
5+
import { IndexedDBPPOMStorage } from '../../lib/ppom/indexed-db-backend';
6+
import * as PPOMModule from '../../lib/ppom/ppom';
7+
import { ControllerInitFunction } from '../types';
8+
import { PPOMControllerInitMessenger } from '../messengers/ppom-controller-messenger';
9+
10+
export const PPOMControllerInit: ControllerInitFunction<
11+
PPOMController,
12+
PPOMControllerMessenger,
13+
PPOMControllerInitMessenger
14+
> = (request) => {
15+
const {
16+
controllerMessenger,
17+
initMessenger,
18+
getController,
19+
getGlobalChainId,
20+
getProvider,
21+
persistedState,
22+
} = request;
23+
24+
const preferencesController = () => getController('PreferencesController');
25+
26+
const controller = new PPOMController({
27+
messenger: controllerMessenger,
28+
storageBackend: new IndexedDBPPOMStorage('PPOMDB', 1),
29+
provider: getProvider(),
30+
ppomProvider: {
31+
// @ts-expect-error Controller and PPOM wrapper have different argument types in `new` and `validateJsonRpc`
32+
PPOM: PPOMModule.PPOM,
33+
ppomInit: () => PPOMModule.default(process.env.PPOM_URI),
34+
},
35+
// @ts-expect-error State type is not `Partial` in controller.
36+
state: persistedState.PPOMController,
37+
chainId: getGlobalChainId(),
38+
securityAlertsEnabled: preferencesController().state.securityAlertsEnabled,
39+
// @ts-expect-error `onPreferencesChange` type signature is incorrect in `PPOMController`
40+
onPreferencesChange: initMessenger.subscribe.bind(
41+
initMessenger,
42+
'PreferencesController:stateChange',
43+
),
44+
// Both values have defaults in `builds.yml` so should always be defined.
45+
cdnBaseUrl: process.env.BLOCKAID_FILE_CDN as string,
46+
blockaidPublicKey: process.env.BLOCKAID_PUBLIC_KEY as string,
47+
});
48+
49+
return {
50+
controller,
51+
};
52+
};

0 commit comments

Comments
 (0)