Skip to content

Commit 9543ad8

Browse files
authored
Merge branch 'develop' into feat-migration-122-redesignedConfirmationsEnabled
2 parents 03dced4 + a8639a2 commit 9543ad8

File tree

66 files changed

+1487
-835
lines changed

Some content is hidden

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

66 files changed

+1487
-835
lines changed
Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,52 @@
1-
# WARNING! It is currently being investigated how to make this faster
2-
# DO NOT blindly copy this workflow, not noticing the slow down,
3-
# because suddenly our tests will take hours to pass CI.
4-
# Hopefully this comment here will help prevent that.
5-
# https://github.com/MetaMask/metamask-extension/issues/25680
6-
71
name: Run unit tests
82

93
on:
4+
push:
5+
branches: [develop, master]
106
pull_request:
117
types: [opened,reopened,synchronize]
128

139
jobs:
14-
test-unit-jest:
10+
test-unit:
1511
runs-on: ubuntu-latest
12+
strategy:
13+
matrix:
14+
shard: [1, 2, 3, 4, 5, 6]
1615
steps:
1716
- name: Checkout repository
1817
uses: actions/checkout@v4
1918

2019
- name: Setup environment
2120
uses: ./.github/actions/setup-environment
2221

23-
- name: test:coverage:jest:dev
24-
run: yarn test:coverage:jest:dev
22+
- name: test:unit:coverage
23+
run: yarn test:unit:coverage --shard=${{ matrix.shard }}/${{ strategy.job-total }}
24+
25+
- name: Rename coverage to shard coverage
26+
run: mv coverage/coverage-final.json coverage/coverage-${{matrix.shard}}.json
27+
28+
- uses: actions/upload-artifact@v4
29+
with:
30+
name: coverage-${{matrix.shard}}
31+
path: coverage/coverage-${{matrix.shard}}.json
32+
33+
report-coverage:
34+
runs-on: ubuntu-latest
35+
needs:
36+
- test-unit
37+
steps:
38+
- name: Checkout repository
39+
uses: actions/checkout@v4
2540

26-
- name: test:coverage:jest
27-
run: yarn test:coverage:jest
41+
- name: Download coverage from shards
42+
uses: actions/download-artifact@v4
43+
with:
44+
path: coverage
45+
pattern: coverage-*
46+
merge-multiple: true
2847

29-
- uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673
48+
- name: Upload coverage to Codecov
49+
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673
3050
with:
3151
token: ${{ secrets.CODECOV_TOKEN }}
3252
fail_ci_if_error: true
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
diff --git a/dist/chunk-37VHIRUJ.js b/dist/chunk-37VHIRUJ.js
2+
index a909a4ef20305665a07db5c25b4a9ff7eb0a447e..98dd75bf33a9716dc6cca96a38d184645f6ec033 100644
3+
--- a/dist/chunk-37VHIRUJ.js
4+
+++ b/dist/chunk-37VHIRUJ.js
5+
@@ -53,8 +53,8 @@ function assertIsKeyringOrigins(value, ErrorWrapper) {
6+
}
7+
function createOriginRegExp(matcher) {
8+
const escaped = matcher.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
9+
- const regex = escaped.replace(/\*/gu, ".*");
10+
- return RegExp(regex, "u");
11+
+ const regex = escaped.replace(/\\\*/gu, '.*');
12+
+ return RegExp(`${regex}$`, 'u');
13+
}
14+
function checkAllowedOrigin(matcher, origin) {
15+
if (matcher === "*" || matcher === origin) {
16+
diff --git a/dist/chunk-K2OTEZZZ.mjs b/dist/chunk-K2OTEZZZ.mjs
17+
index 15be5da7563a5bdf464d7e9c28ed6f04863e378a..7f38bf328e71c1feb2b8850ba050ce9e55801668 100644
18+
--- a/dist/chunk-K2OTEZZZ.mjs
19+
+++ b/dist/chunk-K2OTEZZZ.mjs
20+
@@ -53,8 +53,8 @@ function assertIsKeyringOrigins(value, ErrorWrapper) {
21+
}
22+
function createOriginRegExp(matcher) {
23+
const escaped = matcher.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
24+
- const regex = escaped.replace(/\*/gu, ".*");
25+
- return RegExp(regex, "u");
26+
+ const regex = escaped.replace(/\\\*/gu, '.*');
27+
+ return RegExp(`${regex}$`, 'u');
28+
}
29+
function checkAllowedOrigin(matcher, origin) {
30+
if (matcher === "*" || matcher === origin) {

app/scripts/controllers/mmi-controller.test.ts

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -456,26 +456,6 @@ describe('MMIController', function () {
456456
});
457457
});
458458

459-
describe('getCustodianAccountsByAddress', () => {
460-
it('should return custodian accounts by address', async () => {
461-
CUSTODIAN_TYPES['MOCK-CUSTODIAN-TYPE'] = {
462-
keyringClass: { type: 'mock-keyring-class' },
463-
};
464-
mmiController.addKeyringIfNotExists = jest.fn().mockResolvedValue({
465-
getCustodianAccounts: jest.fn().mockResolvedValue(['account1']),
466-
});
467-
468-
const result = await mmiController.getCustodianAccountsByAddress(
469-
'token',
470-
'envName',
471-
'address',
472-
'mock-custodian-type',
473-
);
474-
475-
expect(result).toEqual(['account1']);
476-
});
477-
});
478-
479459
describe('getCustodianTransactionDeepLink', () => {
480460
it('should return a transaction deep link', async () => {
481461
mmiController.custodyController.getCustodyTypeByAddress = jest

app/scripts/controllers/mmi-controller.ts

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -570,33 +570,6 @@ export default class MMIController extends EventEmitter {
570570
return accounts;
571571
}
572572

573-
async getCustodianAccountsByAddress(
574-
token: string,
575-
envName: string,
576-
address: string,
577-
custodianType: string,
578-
) {
579-
let keyring;
580-
581-
if (custodianType) {
582-
const custodian = CUSTODIAN_TYPES[custodianType.toUpperCase()];
583-
if (!custodian) {
584-
throw new Error('No such custodian');
585-
}
586-
587-
keyring = await this.addKeyringIfNotExists(custodian.keyringClass.type);
588-
} else {
589-
throw new Error('No custodian specified');
590-
}
591-
592-
const accounts = await keyring.getCustodianAccounts(
593-
token,
594-
envName,
595-
address,
596-
);
597-
return accounts;
598-
}
599-
600573
async getCustodianTransactionDeepLink(address: string, txId: string) {
601574
const custodyType = this.custodyController.getCustodyTypeByAddress(
602575
toChecksumHexAddress(address),

app/scripts/lib/ppom/ppom-middleware.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { SecurityAlertResponse } from './types';
2323
jest.mock('./ppom-util');
2424

2525
const SECURITY_ALERT_ID_MOCK = '123';
26+
const INTERNAL_ACCOUNT_ADDRESS = '0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b';
2627

2728
const SECURITY_ALERT_RESPONSE_MOCK: SecurityAlertResponse = {
2829
securityAlertId: SECURITY_ALERT_ID_MOCK,
@@ -69,6 +70,10 @@ const createMiddleware = (
6970
addSignatureSecurityAlertResponse: () => undefined,
7071
};
7172

73+
const accountsController = {
74+
listAccounts: () => [{ address: INTERNAL_ACCOUNT_ADDRESS }],
75+
};
76+
7277
return createPPOMMiddleware(
7378
// TODO: Replace `any` with type
7479
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -82,6 +87,8 @@ const createMiddleware = (
8287
// TODO: Replace `any` with type
8388
// eslint-disable-next-line @typescript-eslint/no-explicit-any
8489
appStateController as any,
90+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
91+
accountsController as any,
8592
updateSecurityAlertResponse,
8693
);
8794
};
@@ -206,6 +213,26 @@ describe('PPOMMiddleware', () => {
206213
expect(validateRequestWithPPOM).not.toHaveBeenCalled();
207214
});
208215

216+
it('does not do validation when request is send to users own account', async () => {
217+
const middlewareFunction = createMiddleware();
218+
219+
const req = {
220+
...JsonRpcRequestStruct,
221+
params: [{ to: INTERNAL_ACCOUNT_ADDRESS }],
222+
method: 'eth_sendTransaction',
223+
securityAlertResponse: undefined,
224+
};
225+
226+
await middlewareFunction(
227+
req,
228+
{ ...JsonRpcResponseStruct },
229+
() => undefined,
230+
);
231+
232+
expect(req.securityAlertResponse).toBeUndefined();
233+
expect(validateRequestWithPPOM).not.toHaveBeenCalled();
234+
});
235+
209236
it('does not do validation for SIWE signature', async () => {
210237
const middlewareFunction = createMiddleware({
211238
securityAlertsEnabled: true,

app/scripts/lib/ppom/ppom-middleware.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { AccountsController } from '@metamask/accounts-controller';
12
import { PPOMController } from '@metamask/ppom-validator';
23
import { NetworkController } from '@metamask/network-controller';
34
import {
@@ -8,6 +9,7 @@ import {
89
} from '@metamask/utils';
910
import { detectSIWE } from '@metamask/controller-utils';
1011

12+
import { MESSAGE_TYPE } from '../../../../shared/constants/app';
1113
import { SIGNING_METHODS } from '../../../../shared/constants/transaction';
1214
import { PreferencesController } from '../../controllers/preferences';
1315
import { AppStateController } from '../../controllers/app-state';
@@ -41,6 +43,7 @@ const CONFIRMATION_METHODS = Object.freeze([
4143
* @param preferencesController - Instance of PreferenceController.
4244
* @param networkController - Instance of NetworkController.
4345
* @param appStateController
46+
* @param accountsController - Instance of AccountsController.
4447
* @param updateSecurityAlertResponse
4548
* @returns PPOMMiddleware function.
4649
*/
@@ -52,6 +55,7 @@ export function createPPOMMiddleware<
5255
preferencesController: PreferencesController,
5356
networkController: NetworkController,
5457
appStateController: AppStateController,
58+
accountsController: AccountsController,
5559
updateSecurityAlertResponse: (
5660
method: string,
5761
signatureAlertId: string,
@@ -82,6 +86,17 @@ export function createPPOMMiddleware<
8286
return;
8387
}
8488

89+
if (req.method === MESSAGE_TYPE.ETH_SEND_TRANSACTION) {
90+
const { to: toAddress } = req?.params?.[0] ?? {};
91+
const internalAccounts = accountsController.listAccounts();
92+
const isToInternalAccount = internalAccounts.some(
93+
({ address }) => address?.toLowerCase() === toAddress?.toLowerCase(),
94+
);
95+
if (isToInternalAccount) {
96+
return;
97+
}
98+
}
99+
85100
const securityAlertId = generateSecurityAlertId();
86101

87102
validateRequestWithPPOM({

app/scripts/lib/transaction/util.test.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ jest.mock('uuid', () => {
3838

3939
const SECURITY_ALERT_ID_MOCK = '123';
4040

41+
const INTERNAL_ACCOUNT_ADDRESS = '0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b';
42+
4143
const TRANSACTION_PARAMS_MOCK: TransactionParams = {
4244
from: '0x1',
4345
};
@@ -69,7 +71,8 @@ const TRANSACTION_REQUEST_MOCK: AddTransactionRequest = {
6971
transactionParams: TRANSACTION_PARAMS_MOCK,
7072
transactionOptions: TRANSACTION_OPTIONS_MOCK,
7173
waitForSubmit: false,
72-
} as AddTransactionRequest;
74+
internalAccounts: [],
75+
} as unknown as AddTransactionRequest;
7376

7477
const SECURITY_ALERT_RESPONSE_MOCK: SecurityAlertResponse = {
7578
result_type: BlockaidResultType.Malicious,
@@ -466,6 +469,37 @@ describe('Transaction Utils', () => {
466469
expect(validateRequestWithPPOMMock).toHaveBeenCalledTimes(0);
467470
});
468471

472+
it('send to users own acccount', async () => {
473+
const sendRequest = {
474+
...request,
475+
transactionParams: {
476+
...request.transactionParams,
477+
to: INTERNAL_ACCOUNT_ADDRESS,
478+
},
479+
};
480+
await addTransaction({
481+
...sendRequest,
482+
securityAlertsEnabled: false,
483+
chainId: '0x1',
484+
internalAccounts: {
485+
address: INTERNAL_ACCOUNT_ADDRESS,
486+
} as InternalAccount,
487+
});
488+
489+
expect(
490+
request.transactionController.addTransaction,
491+
).toHaveBeenCalledTimes(1);
492+
493+
expect(
494+
request.transactionController.addTransaction,
495+
).toHaveBeenCalledWith(
496+
sendRequest.transactionParams,
497+
TRANSACTION_OPTIONS_MOCK,
498+
);
499+
500+
expect(validateRequestWithPPOMMock).toHaveBeenCalledTimes(0);
501+
});
502+
469503
it('unless chain is not supported', async () => {
470504
await addTransaction({
471505
...request,

app/scripts/lib/transaction/util.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ type BaseAddTransactionRequest = {
4343
securityAlertResponse: SecurityAlertResponse,
4444
) => void;
4545
userOperationController: UserOperationController;
46+
internalAccounts: InternalAccount[];
4647
};
4748

4849
type FinalAddTransactionRequest = BaseAddTransactionRequest & {
@@ -223,6 +224,7 @@ function validateSecurity(request: AddTransactionRequest) {
223224
transactionOptions,
224225
transactionParams,
225226
updateSecurityAlertResponse,
227+
internalAccounts,
226228
} = request;
227229

228230
const { type } = transactionOptions;
@@ -240,6 +242,15 @@ function validateSecurity(request: AddTransactionRequest) {
240242
return;
241243
}
242244

245+
if (
246+
internalAccounts.some(
247+
({ address }) =>
248+
address.toLowerCase() === transactionParams.to?.toLowerCase(),
249+
)
250+
) {
251+
return;
252+
}
253+
243254
try {
244255
const { from, to, value, data } = transactionParams;
245256
const { actionId, origin } = transactionOptions;

app/scripts/metamask-controller.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3419,10 +3419,6 @@ export default class MetamaskController extends EventEmitter {
34193419
getCustodianAccounts: this.mmiController.getCustodianAccounts.bind(
34203420
this.mmiController,
34213421
),
3422-
getCustodianAccountsByAddress:
3423-
this.mmiController.getCustodianAccountsByAddress.bind(
3424-
this.mmiController,
3425-
),
34263422
getCustodianTransactionDeepLink:
34273423
this.mmiController.getCustodianTransactionDeepLink.bind(
34283424
this.mmiController,
@@ -4602,6 +4598,7 @@ export default class MetamaskController extends EventEmitter {
46024598
dappRequest,
46034599
}) {
46044600
return {
4601+
internalAccounts: this.accountsController.listAccounts(),
46054602
dappRequest,
46064603
networkClientId:
46074604
dappRequest?.networkClientId ??
@@ -5203,6 +5200,7 @@ export default class MetamaskController extends EventEmitter {
52035200
this.preferencesController,
52045201
this.networkController,
52055202
this.appStateController,
5203+
this.accountsController,
52065204
this.updateSecurityAlertResponse.bind(this),
52075205
),
52085206
);

development/build/transforms/remove-fenced-code.test.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
/**
2+
* @jest-environment node
3+
*/
14
const buildUtils = require('@metamask/build-utils');
25
const { createRemoveFencedCodeTransform } = require('./remove-fenced-code');
36
const transformUtils = require('./utils');
@@ -36,6 +39,10 @@ describe('build/transforms/remove-fenced-code', () => {
3639
lintTransformedFileMock.mockImplementation(() => Promise.resolve());
3740
});
3841

42+
afterEach(() => {
43+
jest.resetAllMocks();
44+
});
45+
3946
it('returns a PassThrough stream for files with ignored extensions', async () => {
4047
const fileContent = '"Valid JSON content"\n';
4148
const stream = createRemoveFencedCodeTransform(

0 commit comments

Comments
 (0)