Skip to content

Commit

Permalink
Merge branch 'develop' into multichain-asset-list
Browse files Browse the repository at this point in the history
  • Loading branch information
salimtb authored Oct 17, 2024
2 parents bfad6e7 + f58d598 commit 54568ff
Show file tree
Hide file tree
Showing 160 changed files with 5,494 additions and 1,326 deletions.
4 changes: 2 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1250,7 +1250,7 @@ jobs:
command: mv ./builds-test-flask-mv2 ./builds
- run:
name: test:e2e:firefox:flask
command: ENABLE_MV3=false .circleci/scripts/test-run-e2e.sh yarn test:e2e:firefox:flask
command: .circleci/scripts/test-run-e2e.sh yarn test:e2e:firefox:flask
no_output_timeout: 5m
- store_artifacts:
path: test-artifacts
Expand Down Expand Up @@ -1393,7 +1393,7 @@ jobs:
command: mv ./builds-test-mv2 ./builds
- run:
name: test:e2e:firefox
command: ENABLE_MV3=false .circleci/scripts/test-run-e2e.sh yarn test:e2e:firefox
command: .circleci/scripts/test-run-e2e.sh yarn test:e2e:firefox
no_output_timeout: 5m
- store_artifacts:
path: test-artifacts
Expand Down
9 changes: 0 additions & 9 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,12 @@ jobs:
name: Run tests
uses: ./.github/workflows/run-tests.yml

sonarcloud:
name: SonarCloud
uses: ./.github/workflows/sonarcloud.yml
secrets:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
needs:
- run-tests

all-jobs-completed:
name: All jobs completed
runs-on: ubuntu-latest
needs:
- check-workflows
- run-tests
- sonarcloud
outputs:
PASSED: ${{ steps.set-output.outputs.PASSED }}
steps:
Expand Down
36 changes: 32 additions & 4 deletions .github/workflows/sonarcloud.yml
Original file line number Diff line number Diff line change
@@ -1,26 +1,54 @@
# This GitHub action will checkout and scan third party code.
# Please ensure that any changes to this action do not perform
# actions that may result in code from that branch being executed
# such as installing dependencies or running build scripts.

name: SonarCloud

on:
workflow_call:
secrets:
SONAR_TOKEN:
required: true
workflow_run:
workflows:
- Run tests
types:
- completed

permissions:
actions: read

jobs:
sonarcloud:
# Only scan code from non-forked repositories that have passed the tests
# This will skip scanning the code for forks, but will run for the main repository on PRs from forks
if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.repository.fork == false }}
name: SonarCloud
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
repository: ${{ github.event.workflow_run.head_repository.full_name }} # Use the repository that triggered the workflow
ref: ${{ github.event.workflow_run.head_branch }} # Use the branch that triggered the workflow
fetch-depth: 0 # Shallow clones should be disabled for better relevancy of analysis

- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: lcov.info
path: coverage
github-token: ${{ github.token }} # This is required when downloading artifacts from a different repository or from a different workflow run.
run-id: ${{ github.event.workflow_run.id }} # Use the workflow id that triggered the workflow

- name: Download sonar-project.properties
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPOSITORY: MetaMask/metamask-extension
run: |
sonar_project_properties=$(gh api -H "Accept: application/vnd.github.raw" "repos/$REPOSITORY/contents/sonar-project.properties")
if [ -z "$sonar_project_properties" ]; then
echo "::error::sonar-project.properties not found in $REPOSITORY. Please make sure this file exists on the default branch."
exit 1
fi
echo "$sonar_project_properties" > sonar-project.properties
- name: SonarCloud Scan
# This is SonarSource/sonarcloud-github-action@v2.0.0
Expand Down
120 changes: 0 additions & 120 deletions .yarn/patches/@metamask-snaps-utils-npm-8.1.1-7d5dd6a26a.patch

This file was deleted.

8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [12.4.1]
### Fixed
- Fix crash on swaps review page ([#27708](https://github.com/MetaMask/metamask-extension/pull/27708))
- Fix bug that could prevent the phishing detection feature from having the most up to date info on which web pages to block ([#27743](https://github.com/MetaMask/metamask-extension/pull/27743))

## [12.4.0]
### Added
- Added a receive button to the home screen, allowing users to easily get their address or QR-code for receiving cryptocurrency ([#26148](https://github.com/MetaMask/metamask-extension/pull/26148))
Expand Down Expand Up @@ -5139,7 +5144,8 @@ Update styles and spacing on the critical error page ([#20350](https://github.c
- Added the ability to restore accounts from seed words.


[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v12.4.0...HEAD
[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v12.4.1...HEAD
[12.4.1]: https://github.com/MetaMask/metamask-extension/compare/v12.4.0...v12.4.1
[12.4.0]: https://github.com/MetaMask/metamask-extension/compare/v12.3.1...v12.4.0
[12.3.1]: https://github.com/MetaMask/metamask-extension/compare/v12.3.0...v12.3.1
[12.3.0]: https://github.com/MetaMask/metamask-extension/compare/v12.2.4...v12.3.0
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,15 @@ If you are using VS Code and are unable to make commits from the source control
To start a development build (e.g. with logging and file watching) run `yarn start`.

#### Development build with wallet state

You can start a development build with a preloaded wallet state, by adding `TEST_SRP='<insert SRP here>'` and `PASSWORD='<insert wallet password here>'` to the `.metamaskrc` file. Then you have the following options:

1. Start the wallet with the default fixture flags, by running `yarn start:with-state`.
2. Check the list of available fixture flags, by running `yarn start:with-state --help`.
3. Start the wallet with custom fixture flags, by running `yarn start:with-state --FIXTURE_NAME=VALUE` for example `yarn start:with-state --withAccounts=100`. You can pass as many flags as you want. The rest of the fixtures will take the default values.

#### Development build with Webpack

You can also start a development build using the `yarn webpack` command, or `yarn webpack --watch`. This uses an alternative build system that is much faster, but not yet production ready. See the [Webpack README](./development/webpack/README.md) for more information.

#### React and Redux DevTools
Expand Down Expand Up @@ -191,7 +194,7 @@ Different build types have different e2e tests sets. In order to run them look i
```console
"test:e2e:chrome:mmi": "SELENIUM_BROWSER=chrome node test/e2e/run-all.js --mmi",
"test:e2e:chrome:snaps": "SELENIUM_BROWSER=chrome node test/e2e/run-all.js --snaps",
"test:e2e:firefox": "ENABLE_MV3=false SELENIUM_BROWSER=firefox node test/e2e/run-all.js",
"test:e2e:firefox": "SELENIUM_BROWSER=firefox node test/e2e/run-all.js",
```

#### Note: Running MMI e2e tests
Expand Down
9 changes: 7 additions & 2 deletions app/_locales/en/messages.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions app/scripts/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { isObject } from '@metamask/utils';
import { ApprovalType } from '@metamask/controller-utils';
import PortStream from 'extension-port-stream';

import { ethErrors } from 'eth-rpc-errors';
import { providerErrors } from '@metamask/rpc-errors';
import { DIALOG_APPROVAL_TYPES } from '@metamask/snaps-rpc-methods';
import { NotificationServicesController } from '@metamask/notification-services-controller';

Expand Down Expand Up @@ -1159,7 +1159,7 @@ export function setupController(
default:
controller.approvalController.reject(
id,
ethErrors.provider.userRejectedRequest(),
providerErrors.userRejectedRequest(),
);
break;
}
Expand Down
99 changes: 99 additions & 0 deletions app/scripts/controllers/mmi-controller.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { mmiKeyringBuilderFactory } from '../mmi-keyring-builder-factory';
import MetaMetricsController from './metametrics';
import { ETH_EOA_METHODS } from '../../../shared/constants/eth-methods';
import { mockNetworkState } from '../../../test/stub/networks';
import { API_REQUEST_LOG_EVENT } from '@metamask-institutional/sdk';

jest.mock('@metamask-institutional/portfolio-dashboard', () => ({
handleMmiPortfolio: jest.fn(),
Expand Down Expand Up @@ -353,6 +354,33 @@ describe('MMIController', function () {
mmiController.mmiConfigurationController.storeConfiguration,
).toHaveBeenCalled();
});

it('should set up API_REQUEST_LOG_EVENT listener on keyring', async () => {
const mockKeyring = {
on: jest.fn(),
getAccounts: jest.fn().mockResolvedValue([]),
getSupportedChains: jest.fn().mockResolvedValue({}),
};

mmiController.addKeyringIfNotExists = jest.fn().mockResolvedValue(mockKeyring);
mmiController.custodyController.getAllCustodyTypes = jest.fn().mockReturnValue(['mock-custody-type']);
mmiController.logAndStoreApiRequest = jest.fn();

await mmiController.onSubmitPassword();

expect(mockKeyring.on).toHaveBeenCalledWith(
API_REQUEST_LOG_EVENT,
expect.any(Function)
);

const mockLogData = { someKey: 'someValue' };
const apiRequestLogEventHandler = mockKeyring.on.mock.calls.find(
call => call[0] === API_REQUEST_LOG_EVENT
)[1];
apiRequestLogEventHandler(mockLogData);

expect(mmiController.logAndStoreApiRequest).toHaveBeenCalledWith(mockLogData);
});
});

describe('connectCustodyAddresses', () => {
Expand Down Expand Up @@ -408,6 +436,54 @@ describe('MMIController', function () {
).toHaveBeenCalled();
expect(result).toEqual(['0x1']);
});

it('should set up API_REQUEST_LOG_EVENT listener on keyring', async () => {
const custodianType = 'mock-custodian-type';
const custodianName = 'mock-custodian-name';
const accounts = {
'0x1': {
name: 'Account 1',
custodianDetails: {},
labels: [],
token: 'token',
chainId: 1,
},
};
CUSTODIAN_TYPES['MOCK-CUSTODIAN-TYPE'] = {
keyringClass: { type: 'mock-keyring-class' },
};

const mockKeyring = {
on: jest.fn(),
setSelectedAddresses: jest.fn(),
addAccounts: jest.fn(),
getStatusMap: jest.fn(),
};

mmiController.addKeyringIfNotExists = jest.fn().mockResolvedValue(mockKeyring);
mmiController.keyringController.getAccounts = jest.fn().mockResolvedValue(['0x2']);
mmiController.keyringController.addNewAccountForKeyring = jest.fn().mockResolvedValue('0x3');
mmiController.custodyController.setAccountDetails = jest.fn();
mmiController.accountTrackerController.syncWithAddresses = jest.fn();
mmiController.storeCustodianSupportedChains = jest.fn();
mmiController.custodyController.storeCustodyStatusMap = jest.fn();
mmiController.logAndStoreApiRequest = jest.fn();

await mmiController.connectCustodyAddresses(custodianType, custodianName, accounts);

expect(mockKeyring.on).toHaveBeenCalledWith(
API_REQUEST_LOG_EVENT,
expect.any(Function)
);

const mockLogData = { someKey: 'someValue' };
const apiRequestLogEventHandler = mockKeyring.on.mock.calls.find(
call => call[0] === API_REQUEST_LOG_EVENT
)[1];
apiRequestLogEventHandler(mockLogData);

expect(mmiController.logAndStoreApiRequest).toHaveBeenCalledWith(mockLogData);
});
});

describe('getCustodianAccounts', () => {
Expand Down Expand Up @@ -783,4 +859,27 @@ describe('MMIController', function () {
).toHaveBeenCalledWith('/new-account/connect');
});
});

describe('logAndStoreApiRequest', () => {
it('should call custodyController.sanitizeAndLogApiCall with the provided log data', async () => {
const mockLogData = { someKey: 'someValue' };
const mockSanitizedLogs = { sanitizedKey: 'sanitizedValue' };

mmiController.custodyController.sanitizeAndLogApiCall = jest.fn().mockResolvedValue(mockSanitizedLogs);

const result = await mmiController.logAndStoreApiRequest(mockLogData);

expect(mmiController.custodyController.sanitizeAndLogApiCall).toHaveBeenCalledWith(mockLogData);
expect(result).toEqual(mockSanitizedLogs);
});

it('should handle errors and throw them', async () => {
const mockLogData = { someKey: 'someValue' };
const mockError = new Error('Sanitize error');

mmiController.custodyController.sanitizeAndLogApiCall = jest.fn().mockRejectedValue(mockError);

await expect(mmiController.logAndStoreApiRequest(mockLogData)).rejects.toThrow('Sanitize error');
});
});
});
24 changes: 22 additions & 2 deletions app/scripts/controllers/mmi-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ import {
import {
REFRESH_TOKEN_CHANGE_EVENT,
INTERACTIVE_REPLACEMENT_TOKEN_CHANGE_EVENT,
API_REQUEST_LOG_EVENT,
} from '@metamask-institutional/sdk';
import { handleMmiPortfolio } from '@metamask-institutional/portfolio-dashboard';
import { TransactionMeta } from '@metamask/transaction-controller';
import { KeyringTypes } from '@metamask/keyring-controller';
import { CustodyController } from '@metamask-institutional/custody-controller';
import { IApiCallLogEntry } from '@metamask-institutional/types';
import { TransactionUpdateController } from '@metamask-institutional/transaction-update';
import { TransactionMeta } from '@metamask/transaction-controller';
import { KeyringTypes } from '@metamask/keyring-controller';
import { SignatureController } from '@metamask/signature-controller';
import {
OriginalRequest,
Expand Down Expand Up @@ -304,6 +306,10 @@ export default class MMIController extends EventEmitter {
},
);

keyring.on(API_REQUEST_LOG_EVENT, (logData: IApiCallLogEntry) => {
this.logAndStoreApiRequest(logData);
});

// store the supported chains for this custodian type
const accounts = await keyring.getAccounts();
addresses = addresses.concat(...accounts);
Expand Down Expand Up @@ -419,6 +425,10 @@ export default class MMIController extends EventEmitter {
},
);

keyring.on(API_REQUEST_LOG_EVENT, (logData: IApiCallLogEntry) => {
this.logAndStoreApiRequest(logData);
});

if (!keyring) {
throw new Error('Unable to get keyring');
}
Expand Down Expand Up @@ -884,4 +894,14 @@ export default class MMIController extends EventEmitter {
this.platform.openExtensionInBrowser(CONNECT_HARDWARE_ROUTE);
return true;
}

async logAndStoreApiRequest(logData: IApiCallLogEntry) {
try {
const logs = await this.custodyController.sanitizeAndLogApiCall(logData);
return logs;
} catch (error) {
log.error('Error fetching extension request logs:', error);
throw error;
}
}
}
1 change: 1 addition & 0 deletions app/scripts/controllers/permissions/specifications.js
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ export const unrestrictedMethods = Object.freeze([
'snap_updateInterface',
'snap_getInterfaceState',
'snap_resolveInterface',
'snap_getCurrencyRate',
///: BEGIN:ONLY_INCLUDE_IF(build-mmi)
'metamaskinstitutional_authenticate',
'metamaskinstitutional_reauthenticate',
Expand Down
4 changes: 2 additions & 2 deletions app/scripts/lib/createMetaRPCHandler.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ethErrors, serializeError } from 'eth-rpc-errors';
import { rpcErrors, serializeError } from '@metamask/rpc-errors';
import { isStreamWritable } from './stream-utils';

const createMetaRPCHandler = (api, outStream) => {
Expand All @@ -9,7 +9,7 @@ const createMetaRPCHandler = (api, outStream) => {
if (!api[data.method]) {
outStream.write({
jsonrpc: '2.0',
error: ethErrors.rpc.methodNotFound({
error: rpcErrors.methodNotFound({
message: `${data.method} not found`,
}),
id: data.id,
Expand Down
1 change: 1 addition & 0 deletions app/scripts/lib/createMetaRPCHandler.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ describe('createMetaRPCHandler', () => {
});
streamTest.on('data', (data) => {
expect(data.error.message).toStrictEqual('foo-error');
expect(data.error.data.cause.message).toStrictEqual('foo-error');
streamTest.end();
});
});
Expand Down
Loading

0 comments on commit 54568ff

Please sign in to comment.