1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 01:39:44 +01:00

Merge remote-tracking branch 'origin/develop' into master-sync

This commit is contained in:
Dan J Miller 2023-05-26 15:08:25 -02:30
commit e5a9dc8dcf
375 changed files with 19885 additions and 13114 deletions

View File

@ -10,6 +10,12 @@ executors:
resource_class: medium+
environment:
NODE_OPTIONS: --max_old_space_size=2048
node-browsers-large:
docker:
- image: cimg/node:16.20-browsers
resource_class: large
environment:
NODE_OPTIONS: --max_old_space_size=2048
shellcheck:
docker:
- image: koalaman/shellcheck-alpine@sha256:dfaf08fab58c158549d3be64fb101c626abc5f16f341b569092577ae207db199
@ -500,7 +506,7 @@ jobs:
- builds-test
prep-build-storybook:
executor: node-browsers-medium-plus
executor: node-browsers-large
steps:
- checkout
- attach_workspace:
@ -551,7 +557,7 @@ jobs:
command: yarn verify-locales --quiet
test-storybook:
executor: node-browsers-medium-plus
executor: node-browsers-large
steps:
- checkout
- attach_workspace:

View File

@ -48,11 +48,14 @@ ignores:
- 'improved-yarn-audit'
- 'nyc'
# storybook
- '@storybook/cli'
- '@storybook/core'
- '@storybook/addon-essentials'
- '@storybook/addon-a11y'
- '@storybook/addon-mdx-gfm'
- '@storybook/builder-webpack5'
- '@storybook/manager-webpack5'
- '@storybook/react-webpack5'
- 'storybook-dark-mode'
- '@whitespace/storybook-addon-html'
- 'react-syntax-highlighter'

177
.github/scripts/label-prs.ts vendored Normal file
View File

@ -0,0 +1,177 @@
import * as core from '@actions/core';
import { context, getOctokit } from '@actions/github';
import { GitHub } from '@actions/github/lib/utils';
main().catch((error: Error): void => {
console.error(error);
process.exit(1);
});
async function main(): Promise<void> {
const token = process.env.GITHUB_TOKEN;
if (!token) {
core.setFailed('GITHUB_TOKEN not found');
process.exit(1);
}
const octokit = getOctokit(token);
const headRef = context.payload.pull_request?.head.ref || '';
let issueNumber = await getIssueNumberFromPullRequestBody();
if (issueNumber === "") {
bailIfIsBranchNameInvalid(headRef);
bailIfIsNotFeatureBranch(headRef);
issueNumber = getIssueNumberFromBranchName(headRef);
}
if (Number(issueNumber) === 0) {
process.exit(0);
}
await updateLabels(octokit, issueNumber);
}
async function getIssueNumberFromPullRequestBody(): Promise<string> {
console.log("Checking if the PR's body references an issue...");
let ISSUE_LINK_IN_PR_DESCRIPTION_REGEX =
/(close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved)\s#\d+/gi;
const prBody = await getPullRequestBody();
let matches = prBody.match(ISSUE_LINK_IN_PR_DESCRIPTION_REGEX);
if (!matches || matches?.length === 0) {
console.log(
'No direct link can be drawn between the PR and an issue from the PR body because no issue number was referenced.',
);
return "";
}
if (matches?.length > 1) {
console.log(
'No direct link can be drawn between the PR and an issue from the PR body because more than one issue number was referenced.',
);
return "";
}
const ISSUE_NUMBER_REGEX = /\d+/;
const issueNumber = matches[0].match(ISSUE_NUMBER_REGEX)?.[0] || '';
console.log(`Found issue number ${issueNumber} in PR body.`);
return issueNumber;
}
async function getPullRequestBody(): Promise<string> {
if (context.eventName !== 'pull_request') {
console.log('This action should only run on pull_request events.');
process.exit(1);
}
const prBody = context.payload.pull_request?.body || '';
return prBody;
}
function bailIfIsBranchNameInvalid(branchName: string): void {
const BRANCH_REGEX =
/^(main|develop|(ci|chore|docs|feat|feature|fix|perf|refactor|revert|style)\/\d*(?:[-](?![-])\w*)*|Version-v\d+\.\d+\.\d+)$/;
const isValidBranchName = new RegExp(BRANCH_REGEX).test(branchName);
if (!isValidBranchName) {
console.log('This branch name does not follow the convention.');
console.log(
'Here are some example branch names that are accepted: "fix/123-description", "feat/123-longer-description", "feature/123", "main", "develop", "Version-v10.24.2".',
);
console.log(
'No issue could be linked to this PR, so no labels were copied',
);
process.exit(0);
}
}
function bailIfIsNotFeatureBranch(branchName: string): void {
if (
branchName === 'main' ||
branchName === 'develop' ||
branchName.startsWith('Version-v')
) {
console.log(`${branchName} is not a feature branch.`);
console.log(
'No issue could be linked to this PR, so no labels were copied',
);
process.exit(0);
}
}
async function updateLabels(octokit: InstanceType<typeof GitHub>, issueNumber: string): Promise<void> {
interface ILabel {
name: string;
};
const owner = context.repo.owner;
const repo = context.repo.repo;
const issue = await octokit.rest.issues.get({
owner: owner,
repo: repo,
issue_number: Number(issueNumber),
});
const getNameFromLabel = (label: ILabel): string => label.name
const issueLabels = issue.data.labels.map(label => getNameFromLabel(label as ILabel));
const prNumber = context.payload.number;
const pr = await octokit.rest.issues.get({
owner: owner,
repo: repo,
issue_number: prNumber,
});
const startingPRLabels = pr.data.labels.map(label => getNameFromLabel(label as ILabel));
const dedupedFinalPRLabels = [
...new Set([...startingPRLabels, ...issueLabels]),
];
const hasIssueAdditionalLabels = !sortedArrayEqual(
startingPRLabels,
dedupedFinalPRLabels,
);
if (hasIssueAdditionalLabels) {
await octokit.rest.issues.update({
owner,
repo,
issue_number: prNumber,
labels: dedupedFinalPRLabels,
});
}
}
function getIssueNumberFromBranchName(branchName: string): string {
console.log('Checking if the branch name references an issue...');
let issueNumber: string;
if (branchName.split('/').length > 1) {
issueNumber = branchName.split('/')[1].split('-')[0];
} else {
issueNumber = branchName.split('-')[0];
}
console.log(`Found issue number ${issueNumber} in branch name.`);
return issueNumber;
}
function sortedArrayEqual(array1: string[], array2: string[]): boolean {
const lengthsAreEqual = array1.length === array2.length;
const everyElementMatchesByIndex = array1.every(
(value: string, index: number): boolean => value === array2[index],
);
return lengthsAreEqual && everyElementMatchesByIndex;
}

27
.github/workflows/label-prs.yml vendored Normal file
View File

@ -0,0 +1,27 @@
name: Label PR
on:
pull_request:
types: [assigned, opened, edited, synchronize, reopened]
jobs:
label-pr:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: '16'
- name: Install Yarn
run: npm install -g yarn
- name: Install dependencies
run: yarn

5
.iyarc
View File

@ -1,11 +1,6 @@
# improved-yarn-audit advisory exclusions
GHSA-257v-vj4p-3w2h
# yarn berry's `yarn npm audit` script reports the following vulnerability but
# it is a false positive. The offending version of 'ws' that is installed is
# 7.1.1 and is included only via remote-redux-devtools which is a devDependency
GHSA-6fc8-4gx4-v693
# request library is subject to SSRF.
# addressed by temporary patch in .yarn/patches/request-npm-2.88.2-f4a57c72c4.patch
GHSA-p8p7-x288-28g6

View File

@ -1,15 +1,13 @@
const path = require('path');
const { ProvidePlugin } = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const { generateIconNames } = require('../development/generate-icon-names');
module.exports = {
core: {
builder: 'webpack5',
disableTelemetry: true,
},
features: {
buildStoriesJson: true,
},
features: { buildStoriesJson: true },
stories: [
'../ui/**/*.stories.js',
'../ui/**/*.stories.tsx',
@ -23,19 +21,14 @@ module.exports = {
'@storybook/addon-knobs',
'./i18n-party-addon/register.js',
'storybook-dark-mode',
'@whitespace/storybook-addon-html'
'@whitespace/storybook-addon-html',
'@storybook/addon-mdx-gfm',
],
staticDirs: ['../app', './images'],
// Uses babel.config.js settings and prevents "Missing class properties transform" error
babel: async (options) => ({ overrides: options.overrides }),
// Sets env variables https://storybook.js.org/docs/react/configure/environment-variables/
env: async (config) => {
return {
...config,
// Creates the icon names environment variable for the component-library/icon/icon.js component
ICON_NAMES: generateIconNames(),
};
},
babel: async (options) => ({
overrides: options.overrides,
}),
webpackFinal: async (config) => {
config.context = process.cwd();
config.node = {
@ -54,7 +47,10 @@ module.exports = {
os: false,
path: false,
stream: require.resolve('stream-browserify'),
_stream_transform: require.resolve('readable-stream/lib/_stream_transform.js'),
zlib: false,
_stream_transform: require.resolve(
'readable-stream/lib/_stream_transform.js',
),
};
config.module.strictExportPresence = true;
config.module.rules.push({
@ -102,4 +98,11 @@ module.exports = {
);
return config;
},
docs: {
autodocs: true,
},
framework: {
name: '@storybook/react-webpack5',
options: {},
},
};

View File

@ -1,5 +1,9 @@
/*
* The addParameters and addDecorator APIs to add global decorators and parameters, exported by the various frameworks (e.g. @storybook/react) and @storybook/client were deprecated in 6.0 and have been removed in 7.0.
Instead, use export const parameters = {}; and export const decorators = []; in your .storybook/preview.js. Addon authors similarly should use such an export in a preview entry file (see Preview entries).
* */
import React, { useEffect, useState } from 'react';
import { addDecorator, addParameters } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { Provider } from 'react-redux';
import configureStore from '../ui/store/store';
@ -13,9 +17,9 @@ import { Router } from 'react-router-dom';
import { createBrowserHistory } from 'history';
import { _setBackgroundConnection } from '../ui/store/action-queue';
import MetaMaskStorybookTheme from './metamask-storybook-theme';
import addons from '@storybook/addons';
import { addons } from '@storybook/addons';
addParameters({
export const parameters = {
backgrounds: {
default: 'default',
values: [
@ -41,7 +45,7 @@ addParameters({
controls: {
expanded: true,
},
});
};
export const globalTypes = {
locale: {
@ -117,4 +121,6 @@ const metamaskDecorator = (story, context) => {
);
};
addDecorator(metamaskDecorator);
export const decorators = [
metamaskDecorator,
];

View File

@ -598,7 +598,7 @@ const state = {
nextNonce: 71,
connectedStatusPopoverHasBeenShown: true,
swapsWelcomeMessageHasBeenShown: true,
defaultHomeActiveTabName: 'Assets',
defaultHomeActiveTabName: 'Tokens',
providerConfig: {
type: 'goerli',
ticker: 'ETH',

View File

@ -0,0 +1,12 @@
diff --git a/lib/index.js b/lib/index.js
index c991f62dc64553502e9911a7f21e77e008d7f438..e503c7494d21b13df85b10e1657b2af8ca4d964f 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -222,7 +222,6 @@ var _transform = require("./transform");
var _transformFile = require("./transform-file");
var _transformAst = require("./transform-ast");
var _parse = require("./parse");
-var thisFile = require("./index");
const version = "7.21.5";
exports.version = version;
const DEFAULT_EXTENSIONS = Object.freeze([".js", ".jsx", ".es6", ".es", ".mjs", ".cjs"]);

View File

@ -0,0 +1,38 @@
diff --git a/dist/AssetsContractController.js b/dist/AssetsContractController.js
index 332c87d7cc5687dec4d80ec3c51dcc4bda632c32..1d88cd313efb00c9c9b57f6824ed74bbca6349e3 100644
--- a/dist/AssetsContractController.js
+++ b/dist/AssetsContractController.js
@@ -33,6 +33,7 @@ exports.SINGLE_CALL_BALANCES_ADDRESS_BY_CHAINID = {
[assetsUtil_1.SupportedTokenDetectionNetworks.bsc]: '0x2352c63A83f9Fd126af8676146721Fa00924d7e4',
[assetsUtil_1.SupportedTokenDetectionNetworks.polygon]: '0x2352c63A83f9Fd126af8676146721Fa00924d7e4',
[assetsUtil_1.SupportedTokenDetectionNetworks.avax]: '0xD023D153a0DFa485130ECFdE2FAA7e612EF94818',
+ [assetsUtil_1.SupportedTokenDetectionNetworks.aurora]: '0x1286415D333855237f89Df27D388127181448538',
};
exports.MISSING_PROVIDER_ERROR = 'AssetsContractController failed to set the provider correctly. A provider must be set for this method to be available';
/**
diff --git a/dist/assetsUtil.d.ts b/dist/assetsUtil.d.ts
index 1b69903a3f8e19f5a451c94791ea16fb18e94d93..d45fe80652fea24d19b2b30dd9af7e6219939153 100644
--- a/dist/assetsUtil.d.ts
+++ b/dist/assetsUtil.d.ts
@@ -45,7 +45,8 @@ export declare enum SupportedTokenDetectionNetworks {
mainnet = "1",
bsc = "56",
polygon = "137",
- avax = "43114"
+ avax = "43114",
+ aurora = "1313161554"
}
/**
* Check if token detection is enabled for certain networks.
diff --git a/dist/assetsUtil.js b/dist/assetsUtil.js
index 4b54e82504cdfae1d937860b0b89b14860385b8e..232228688454d32df818065119dff104f5b0c16c 100644
--- a/dist/assetsUtil.js
+++ b/dist/assetsUtil.js
@@ -120,6 +120,7 @@ var SupportedTokenDetectionNetworks;
SupportedTokenDetectionNetworks["bsc"] = "56";
SupportedTokenDetectionNetworks["polygon"] = "137";
SupportedTokenDetectionNetworks["avax"] = "43114";
+ SupportedTokenDetectionNetworks["aurora"] = "1313161554";
})(SupportedTokenDetectionNetworks = exports.SupportedTokenDetectionNetworks || (exports.SupportedTokenDetectionNetworks = {}));
/**
* Check if token detection is enabled for certain networks.

View File

@ -398,9 +398,6 @@
"assetOptions": {
"message": "Asset-Optionen"
},
"assets": {
"message": "Vermögenswerte"
},
"attemptSendingAssets": {
"message": "Wenn Sie versuchen, Assets direkt von einem Netzwerk in ein anderes zu senden, kann dies zu einem dauerhaften Asset-Verlust führen. Verwenden Sie unbedingt eine Bridge."
},
@ -1570,9 +1567,6 @@
"history": {
"message": "Verlauf"
},
"holdToReveal": {
"message": "Halten, um GWP anzuzeigen"
},
"holdToRevealContent1": {
"message": "Ihre geheime Wiederherstellungsphrase bietet $1",
"description": "$1 is a bolded text with the message from 'holdToRevealContent2'"
@ -1593,9 +1587,6 @@
"message": "Betrüger aber schon.",
"description": "The text link in 'holdToRevealContent3'"
},
"holdToRevealTitle": {
"message": "Bewahren Sie Ihre GWP sicher auf"
},
"ignoreAll": {
"message": "Alle ignorieren"
},
@ -3059,9 +3050,6 @@
"searchResults": {
"message": "Suchergebnisse"
},
"searchSettings": {
"message": "In Einstellungen suchen"
},
"searchTokens": {
"message": "Token suchen"
},

View File

@ -398,9 +398,6 @@
"assetOptions": {
"message": "Επιλογές περιουσιακών στοιχείων"
},
"assets": {
"message": "Περιουσιακά στοιχεία"
},
"attemptSendingAssets": {
"message": "Εάν επιχειρήσετε να στείλετε περιουσιακά στοιχεία απευθείας από ένα δίκτυο σε ένα άλλο, αυτό ενδέχεται να οδηγήσει σε μόνιμη απώλεια περιουσιακών στοιχείων. Βεβαιωθείτε ότι χρησιμοποιείτε μια διασύνδεση."
},
@ -1570,9 +1567,6 @@
"history": {
"message": "Ιστορικό"
},
"holdToReveal": {
"message": "Κρατήστε πατημένο για αποκάλυψη της ΜΦΑ"
},
"holdToRevealContent1": {
"message": "Η Μυστική σας Φράση Ανάκτησης παρέχει $1",
"description": "$1 is a bolded text with the message from 'holdToRevealContent2'"
@ -1593,9 +1587,6 @@
"message": "αλλά οι απατεώνες μπορεί να το κάνουν.",
"description": "The text link in 'holdToRevealContent3'"
},
"holdToRevealTitle": {
"message": "Κρατήστε τη ΜΦΑ σας ασφαλή"
},
"ignoreAll": {
"message": "Αγνόηση όλων"
},
@ -3056,12 +3047,6 @@
"searchAccounts": {
"message": "Αναζήτηση Λογαριασμών"
},
"searchResults": {
"message": "Αποτελέσματα Αναζήτησης"
},
"searchSettings": {
"message": "Αναζήτηση στις Ρυθμίσεις"
},
"searchTokens": {
"message": "Αναζήτηση Tokens"
},

View File

@ -441,9 +441,6 @@
"assetOptions": {
"message": "Asset options"
},
"assets": {
"message": "Assets"
},
"attemptSendingAssets": {
"message": "If you attempt to send assets directly from one network to another, this may result in permanent asset loss. Make sure to use a bridge."
},
@ -673,6 +670,9 @@
"coingecko": {
"message": "CoinGecko"
},
"compliance": {
"message": "Compliance"
},
"complianceActivatedDesc": {
"message": "You can now use compliance in MetaMask Institutional. Receiving AML/CFT analysis within the confirmation screen on all the addresses you interact with."
},
@ -733,6 +733,9 @@
"connectAccountOrCreate": {
"message": "Connect account or create new"
},
"connectCustodialAccountMenu": {
"message": "Connect Custodial Account"
},
"connectCustodialAccountMsg": {
"message": "Please choose the custodian you want to connect in order to add or refresh a token."
},
@ -989,6 +992,9 @@
"custodySessionExpired": {
"message": "Custodian session expired."
},
"custodyWrongChain": {
"message": "This account is not set up for use with $1"
},
"custom": {
"message": "Advanced"
},
@ -1412,6 +1418,9 @@
"enterMaxSpendLimit": {
"message": "Enter max spend limit"
},
"enterOptionalPassword": {
"message": "Enter optional password"
},
"enterPassword": {
"message": "Enter password"
},
@ -1754,9 +1763,6 @@
"history": {
"message": "History"
},
"holdToReveal": {
"message": "Hold to reveal SRP"
},
"holdToRevealContent1": {
"message": "Your Secret Recovery Phrase provides $1",
"description": "$1 is a bolded text with the message from 'holdToRevealContent2'"
@ -1777,9 +1783,28 @@
"message": "but phishers might.",
"description": "The text link in 'holdToRevealContent3'"
},
"holdToRevealTitle": {
"holdToRevealContentPrivateKey1": {
"message": "Your Private Key provides $1",
"description": "$1 is a bolded text with the message from 'holdToRevealContentPrivateKey2'"
},
"holdToRevealContentPrivateKey2": {
"message": "full access to your wallet and funds.",
"description": "Is the bolded text in 'holdToRevealContentPrivateKey2'"
},
"holdToRevealLockedLabel": { "message": "hold to reveal circle locked" },
"holdToRevealPrivateKey": {
"message": "Hold to reveal Private Key"
},
"holdToRevealPrivateKeyTitle": {
"message": "Keep your private key safe"
},
"holdToRevealSRP": {
"message": "Hold to reveal SRP"
},
"holdToRevealSRPTitle": {
"message": "Keep your SRP safe"
},
"holdToRevealUnlockedLabel": { "message": "hold to reveal circle unlocked" },
"id": {
"message": "Id"
},
@ -2500,6 +2525,12 @@
"notEnoughGas": {
"message": "Not enough gas"
},
"note": {
"message": "Note"
},
"notePlaceholder": {
"message": "The approver will see this note when approving the transaction at the custodian."
},
"notifications": {
"message": "Notifications"
},
@ -3145,6 +3176,9 @@
"portfolio": {
"message": "Portfolio"
},
"portfolioDashboard": {
"message": "Portfolio Dashboard"
},
"portfolioView": {
"message": "Portfolio view"
},
@ -3491,9 +3525,6 @@
"searchResults": {
"message": "Search results"
},
"searchSettings": {
"message": "Search in Settings"
},
"searchTokens": {
"message": "Search tokens"
},
@ -4540,6 +4571,9 @@
"tokenSymbol": {
"message": "Token symbol"
},
"tokens": {
"message": "Tokens"
},
"tokensFoundTitle": {
"message": "$1 new tokens found",
"description": "$1 is the number of new tokens detected"
@ -4652,6 +4686,9 @@
"transactionHistoryTotalGasFee": {
"message": "Total gas fee"
},
"transactionNote": {
"message": "Transaction note"
},
"transactionResubmitted": {
"message": "Transaction resubmitted with estimated gas fee increased to $1 at $2"
},
@ -4892,6 +4929,9 @@
"viewOnOpensea": {
"message": "View on Opensea"
},
"viewinCustodianApp": {
"message": "View in custodian app"
},
"viewinExplorer": {
"message": "View $1 in explorer",
"description": "$1 is the action type. e.g (Account, Transaction, Swap)"

View File

@ -398,9 +398,6 @@
"assetOptions": {
"message": "Opciones de activos"
},
"assets": {
"message": "Activos"
},
"attemptSendingAssets": {
"message": "Si intenta enviar activos directamente de una red a otra, esto puede provocar la pérdida permanente de activos. Asegúrese de utilizar un puente."
},
@ -1570,9 +1567,6 @@
"history": {
"message": "Historial"
},
"holdToReveal": {
"message": "Mantenga presionado para mostrar la SRP"
},
"holdToRevealContent1": {
"message": "Su frase secreta de recuperación proporciona $1",
"description": "$1 is a bolded text with the message from 'holdToRevealContent2'"
@ -1593,9 +1587,6 @@
"message": "pero los defraudadores sí.",
"description": "The text link in 'holdToRevealContent3'"
},
"holdToRevealTitle": {
"message": "Mantenga segura su SRP"
},
"ignoreAll": {
"message": "Ignorar todo"
},
@ -3059,9 +3050,6 @@
"searchResults": {
"message": "Resultados de la búsqueda"
},
"searchSettings": {
"message": "Buscar en Configuración"
},
"searchTokens": {
"message": "Buscar tokens"
},

View File

@ -229,9 +229,6 @@
"assetOptions": {
"message": "Opciones de activos"
},
"assets": {
"message": "Activos"
},
"attemptingConnect": {
"message": "Intentando una conexión a la cadena de bloques."
},

View File

@ -398,9 +398,6 @@
"assetOptions": {
"message": "Options dactifs"
},
"assets": {
"message": "Actifs"
},
"attemptSendingAssets": {
"message": "Si vous essayez denvoyer des actifs directement dun réseau à un autre, une perte permanente des actifs pourrait en résulter. Assurez-vous dutiliser une passerelle."
},
@ -1570,9 +1567,6 @@
"history": {
"message": "Historique"
},
"holdToReveal": {
"message": "Appuyez longuement pour révéler la PSR"
},
"holdToRevealContent1": {
"message": "Votre phrase secrète de récupération donne $1",
"description": "$1 is a bolded text with the message from 'holdToRevealContent2'"
@ -1593,9 +1587,6 @@
"message": "mais les hameçonneurs pourraient le faire.",
"description": "The text link in 'holdToRevealContent3'"
},
"holdToRevealTitle": {
"message": "Conservez votre PSR en lieu sûr"
},
"ignoreAll": {
"message": "Ignorer tout"
},
@ -3059,9 +3050,6 @@
"searchResults": {
"message": "Résultats de la recherche"
},
"searchSettings": {
"message": "Rechercher dans les paramètres"
},
"searchTokens": {
"message": "Rechercher des jetons"
},

View File

@ -398,9 +398,6 @@
"assetOptions": {
"message": "एसेट विकल्प"
},
"assets": {
"message": "परिसंपत्तियां"
},
"attemptSendingAssets": {
"message": "यदि आप ऐसेट्स को सीधे एक नेटवर्क से दूसरे नेटवर्क पर भेजने का प्रयास करते हैं, तो इसके परिणामस्वरूप स्थायी ऐसेट्स का नुकसान हो सकता है। ब्रिज का उपयोग करना सुनिश्चित करें।"
},
@ -1570,9 +1567,6 @@
"history": {
"message": "इतिहास"
},
"holdToReveal": {
"message": "SRP देखने के लिए होल्ड करें"
},
"holdToRevealContent1": {
"message": "आपका सीक्रेट रिकवरी फ्रेज $1 प्रदान करता है",
"description": "$1 is a bolded text with the message from 'holdToRevealContent2'"
@ -1593,9 +1587,6 @@
"message": "लेकिन फिशर कर सकते हैं।",
"description": "The text link in 'holdToRevealContent3'"
},
"holdToRevealTitle": {
"message": "अपने SRP को सुरक्षित रखें"
},
"ignoreAll": {
"message": "सभी को अनदेखा करें"
},
@ -3059,9 +3050,6 @@
"searchResults": {
"message": "खोज परिणाम"
},
"searchSettings": {
"message": "सेटिंग्स में खोजें"
},
"searchTokens": {
"message": "टोकन खोजें"
},

View File

@ -398,9 +398,6 @@
"assetOptions": {
"message": "Opsi aset"
},
"assets": {
"message": "Aset"
},
"attemptSendingAssets": {
"message": "Jika Anda mencoba untuk mengirim aset secara langsung dari satu jaringan ke jaringan lain, aset Anda berpotensi hilang secara permanen. Pastikan untuk menggunakan penghubung."
},
@ -1570,9 +1567,6 @@
"history": {
"message": "Riwayat"
},
"holdToReveal": {
"message": "Tahan untuk mengungkap FPR"
},
"holdToRevealContent1": {
"message": "Frasa Pemulihan Rahasia memberikan $1",
"description": "$1 is a bolded text with the message from 'holdToRevealContent2'"
@ -1593,9 +1587,6 @@
"message": "tetapi penipu akan mencoba memintanya.",
"description": "The text link in 'holdToRevealContent3'"
},
"holdToRevealTitle": {
"message": "Jaga keamanan FPR Anda"
},
"ignoreAll": {
"message": "Abaikan semua"
},
@ -3059,9 +3050,6 @@
"searchResults": {
"message": "Cari hasil"
},
"searchSettings": {
"message": "Cari di Pengaturan"
},
"searchTokens": {
"message": "Cari token"
},

View File

@ -315,9 +315,6 @@
"assetOptions": {
"message": "Opzioni asset"
},
"assets": {
"message": "Patrimonio"
},
"attemptSendingAssets": {
"message": "Se si tenta di inviare risorse direttamente da una rete all'altra, ciò potrebbe comportare una perdita permanente della risorca coinvolta. Assicurati di usare un bridge."
},

View File

@ -398,9 +398,6 @@
"assetOptions": {
"message": "アセットのオプション"
},
"assets": {
"message": "アセット"
},
"attemptSendingAssets": {
"message": "1 つのネットワークから別のネットワークに直接アセットを送ろうとすると、アセットが永久に失われる可能性があります。必ずブリッジを使用してください。"
},
@ -1570,9 +1567,6 @@
"history": {
"message": "履歴"
},
"holdToReveal": {
"message": "長押しして SRP を表示"
},
"holdToRevealContent1": {
"message": "秘密のリカバリーフレーズは$1を提供します。",
"description": "$1 is a bolded text with the message from 'holdToRevealContent2'"
@ -1593,9 +1587,6 @@
"message": "もし尋ねられた場合はフィッシング詐欺の可能性があります。",
"description": "The text link in 'holdToRevealContent3'"
},
"holdToRevealTitle": {
"message": "SRP は安全に保管してください"
},
"ignoreAll": {
"message": "すべて無視"
},
@ -3059,9 +3050,6 @@
"searchResults": {
"message": "検索結果"
},
"searchSettings": {
"message": "設定で検索"
},
"searchTokens": {
"message": "トークンを検索"
},

View File

@ -398,9 +398,6 @@
"assetOptions": {
"message": "자산 옵션"
},
"assets": {
"message": "자산"
},
"attemptSendingAssets": {
"message": "한 네트워크에서 다른 네트워크로 자산을 직접 전송하면 자산이 영구적으로 손실될 수 있습니다. 반드시 브릿지를 이용하세요."
},
@ -1570,9 +1567,6 @@
"history": {
"message": "기록"
},
"holdToReveal": {
"message": "눌러서 SRP 확인"
},
"holdToRevealContent1": {
"message": "비밀 복구 구문이 있으면 $1 기능을 사용할 수 있습니다",
"description": "$1 is a bolded text with the message from 'holdToRevealContent2'"
@ -1593,9 +1587,6 @@
"message": "오히려 피싱 사기꾼들이 요구할 수 있으니 주의가 필요합니다.",
"description": "The text link in 'holdToRevealContent3'"
},
"holdToRevealTitle": {
"message": "SRP를 안전하게 보관하세요"
},
"ignoreAll": {
"message": "모두 무시"
},
@ -3059,9 +3050,6 @@
"searchResults": {
"message": "검색 결과"
},
"searchSettings": {
"message": "설정에서 찾기"
},
"searchTokens": {
"message": "토큰 검색"
},

View File

@ -140,9 +140,6 @@
"assetOptions": {
"message": "Mga opsyon sa asset"
},
"assets": {
"message": "Mga Asset"
},
"attemptingConnect": {
"message": "Sinusubukang kumonekta sa blockchain."
},

View File

@ -398,9 +398,6 @@
"assetOptions": {
"message": "Opções do ativo"
},
"assets": {
"message": "Ativos"
},
"attemptSendingAssets": {
"message": "Se você tentar enviar ativos diretamente de uma rede para outra, isso poderá resultar na perda permanente deles. Certifique-se de usar uma ponte."
},
@ -1570,9 +1567,6 @@
"history": {
"message": "Histórico"
},
"holdToReveal": {
"message": "Segure para revelar a FRS"
},
"holdToRevealContent1": {
"message": "Sua Frase de Recuperação Secreta concede $1",
"description": "$1 is a bolded text with the message from 'holdToRevealContent2'"
@ -1593,9 +1587,6 @@
"message": "mas os phishers talvez solicitem.",
"description": "The text link in 'holdToRevealContent3'"
},
"holdToRevealTitle": {
"message": "Mantenha sua FRS em segurança"
},
"ignoreAll": {
"message": "Ignorar tudo"
},
@ -3059,9 +3050,6 @@
"searchResults": {
"message": "Resultados da busca"
},
"searchSettings": {
"message": "Buscar nas configurações"
},
"searchTokens": {
"message": "Buscar tokens"
},

View File

@ -229,9 +229,6 @@
"assetOptions": {
"message": "Opções do ativo"
},
"assets": {
"message": "Ativos"
},
"attemptingConnect": {
"message": "Tentando conexão com o blockchain."
},

View File

@ -398,9 +398,6 @@
"assetOptions": {
"message": "Параметры актива"
},
"assets": {
"message": "Активы"
},
"attemptSendingAssets": {
"message": "Попытка отправки активов напрямую из одной сети в другую может привести к необратимой потере активов. Следует использовать мост."
},
@ -1570,9 +1567,6 @@
"history": {
"message": "История"
},
"holdToReveal": {
"message": "Удерживайте для отображения СВФ"
},
"holdToRevealContent1": {
"message": "Ваша секретная фраза для восстановления дает $1",
"description": "$1 is a bolded text with the message from 'holdToRevealContent2'"
@ -1593,9 +1587,6 @@
"message": "но злоумышленники-фишеры могут.",
"description": "The text link in 'holdToRevealContent3'"
},
"holdToRevealTitle": {
"message": "Обеспечьте безопасность своей СВФ"
},
"ignoreAll": {
"message": "Игнорировать все"
},
@ -3059,9 +3050,6 @@
"searchResults": {
"message": "Результаты поиска"
},
"searchSettings": {
"message": "Поиск в настройках"
},
"searchTokens": {
"message": "Поиск токенов"
},

View File

@ -398,9 +398,6 @@
"assetOptions": {
"message": "Mga opsyon ng asset"
},
"assets": {
"message": "Mga Asset"
},
"attemptSendingAssets": {
"message": "Kung tatangkain mong magpadala ng mga asset nang direkta mula sa isang network papunta sa isa pa, maaari itong magresulta sa permanenteng pagkawala ng asset. Siguraduhing gumamit ng tulay."
},
@ -1570,9 +1567,6 @@
"history": {
"message": "History"
},
"holdToReveal": {
"message": "I-hold para ipakita ang SRP"
},
"holdToRevealContent1": {
"message": "Ang iyong Secret Recovery Phrase ay nagbibigay ng $1",
"description": "$1 is a bolded text with the message from 'holdToRevealContent2'"
@ -1593,9 +1587,6 @@
"message": "ngunit maaring hingin ng mga phisher.",
"description": "The text link in 'holdToRevealContent3'"
},
"holdToRevealTitle": {
"message": "Ingatan ang iyong SRP"
},
"ignoreAll": {
"message": "Huwag pansinin ang lahat"
},
@ -3059,9 +3050,6 @@
"searchResults": {
"message": "Mga Resulta ng Paghahanap"
},
"searchSettings": {
"message": "Maghanap sa mga Setting"
},
"searchTokens": {
"message": "Maghanap ng Mga Token"
},

View File

@ -398,9 +398,6 @@
"assetOptions": {
"message": "Varlık seçenekleri"
},
"assets": {
"message": "Varlıklar"
},
"attemptSendingAssets": {
"message": "Varlıkları doğrudan bir ağdan diğerine göndermeye çalışırsanız bu durum kalıcı varlık kaybına neden olabilir. Bir köprü kullandığınızdan emin olun."
},
@ -1570,9 +1567,6 @@
"history": {
"message": "Geçmiş"
},
"holdToReveal": {
"message": "GKİ'yi göstermek için basılı tut"
},
"holdToRevealContent1": {
"message": "Gizli Kurtarma İfadeniz: $1",
"description": "$1 is a bolded text with the message from 'holdToRevealContent2'"
@ -1593,9 +1587,6 @@
"message": "ancak dolandırıcılar talep edilebilir.",
"description": "The text link in 'holdToRevealContent3'"
},
"holdToRevealTitle": {
"message": "GKİ'nizi güvende tutun"
},
"ignoreAll": {
"message": "Tümünü yoksay"
},
@ -3059,9 +3050,6 @@
"searchResults": {
"message": "Arama sonuçları"
},
"searchSettings": {
"message": "Ayarlarda ara"
},
"searchTokens": {
"message": "Token ara"
},

View File

@ -398,9 +398,6 @@
"assetOptions": {
"message": "Tùy chọn tài sản"
},
"assets": {
"message": "Tài sản"
},
"attemptSendingAssets": {
"message": "Nếu bạn cố gắng gửi tài sản trực tiếp từ mạng này sang mạng khác, bạn có thể bị mất tài sản vĩnh viễn. Hãy nhớ sử dụng cầu nối."
},
@ -1570,9 +1567,6 @@
"history": {
"message": "Lịch sử"
},
"holdToReveal": {
"message": "Giữ để hiển thị Cụm từ khôi phục bí mật"
},
"holdToRevealContent1": {
"message": "Cụm từ khôi phục bí mật của bạn cung cấp $1",
"description": "$1 is a bolded text with the message from 'holdToRevealContent2'"
@ -1593,9 +1587,6 @@
"message": "nhưng những kẻ lừa đảo qua mạng thì có.",
"description": "The text link in 'holdToRevealContent3'"
},
"holdToRevealTitle": {
"message": "Đảm bảo an toàn cho Cụm từ khôi phục bí mật của bạn"
},
"ignoreAll": {
"message": "Bỏ qua tất cả"
},
@ -3059,9 +3050,6 @@
"searchResults": {
"message": "Kết quả tìm kiếm"
},
"searchSettings": {
"message": "Tìm kiếm trong phần Cài đặt"
},
"searchTokens": {
"message": "Tìm kiếm token"
},

View File

@ -398,9 +398,6 @@
"assetOptions": {
"message": "资产选项"
},
"assets": {
"message": "资产"
},
"attemptSendingAssets": {
"message": "如果您试图将资产从一个网络直接发送到另一个网络,这可能会导致永久的资产损失。必须使用桥来进行。"
},
@ -1570,9 +1567,6 @@
"history": {
"message": "历史记录"
},
"holdToReveal": {
"message": "按住以显示 SRP"
},
"holdToRevealContent1": {
"message": "您的助记词提供 $1",
"description": "$1 is a bolded text with the message from 'holdToRevealContent2'"
@ -1593,9 +1587,6 @@
"message": "但网络钓鱼者可能会。",
"description": "The text link in 'holdToRevealContent3'"
},
"holdToRevealTitle": {
"message": "确保 SRP 的安全"
},
"ignoreAll": {
"message": "忽略所有"
},
@ -3059,9 +3050,6 @@
"searchResults": {
"message": "搜索结果"
},
"searchSettings": {
"message": "在设置中搜索"
},
"searchTokens": {
"message": "搜索代币"
},

View File

@ -139,9 +139,6 @@
"assetOptions": {
"message": "資產選項"
},
"assets": {
"message": "資產"
},
"attemptingConnect": {
"message": "正在嘗試連結區塊鏈。"
},

View File

@ -0,0 +1,6 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M12.36 6L12.76 8H18V14H14.64L14.24 12H7V6H12.36ZM14 4H5V21H7V14H12.6L13 16H20V6H14.4L14 4Z"
fill="black"
/>
</svg>

After

Width:  |  Height:  |  Size: 231 B

View File

@ -0,0 +1,8 @@
<svg width="20" height="20" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="surface1">
<path
d="M 10.351562 9.167969 L 10.351562 9.777344 C 10.351562 10.449219 9.835938 11 9.203125 11 L 1.148438 11 C 0.511719 11 0 10.449219 0 9.777344 L 0 1.222656 C 0 0.550781 0.511719 0 1.148438 0 L 9.203125 0 C 9.835938 0 10.351562 0.550781 10.351562 1.222656 L 10.351562 1.832031 L 5.175781 1.832031 C 4.539062 1.832031 4.027344 2.382812 4.027344 3.054688 L 4.027344 7.945312 C 4.027344 8.617188 4.539062 9.167969 5.175781 9.167969 Z M 5.175781 7.945312 L 10.929688 7.945312 L 10.929688 3.054688 L 5.175781 3.054688 Z M 7.476562 6.417969 C 7 6.417969 6.613281 6.007812 6.613281 5.5 C 6.613281 4.992188 7 4.582031 7.476562 4.582031 C 7.953125 4.582031 8.339844 4.992188 8.339844 5.5 C 8.339844 6.007812 7.953125 6.417969 7.476562 6.417969 Z M 7.476562 6.417969 "
fill="black"
/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 928 B

View File

@ -0,0 +1,6 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M0.75 17.25V15.5083L2.125 14.1333V17.25H0.75ZM4.53125 17.25V11.8417L5.90625 10.4667V17.25H4.53125ZM8.3125 17.25V10.4667L9.6875 11.8646V17.25H8.3125ZM12.0938 17.25V11.8646L13.4688 10.4896V17.25H12.0938ZM15.875 17.25V8.175L17.25 6.8V17.25H15.875ZM0.75 11.8417V9.89375L7.16667 3.52292L10.8333 7.18958L17.25 0.75V2.69792L10.8333 9.1375L7.16667 5.47083L0.75 11.8417Z"
fill="black"
/>
</svg>

After

Width:  |  Height:  |  Size: 502 B

View File

@ -1,4 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 0L0 16H16L8 0ZM8 3.36842L13.4764 14.3158H2.52364L8 3.36842ZM7.27273 6.73684V10.1053H8.72727V6.73684H7.27273ZM7.27273 11.7895V13.4737H8.72727V11.7895" fill="#D73A49"/>
</svg>

Before

Width:  |  Height:  |  Size: 282 B

View File

@ -9,6 +9,9 @@ import debounce from 'debounce-stream';
import log from 'loglevel';
import browser from 'webextension-polyfill';
import { storeAsStream } from '@metamask/obs-store';
///: BEGIN:ONLY_INCLUDE_IN(snaps)
import { ApprovalType } from '@metamask/controller-utils';
///: END:ONLY_INCLUDE_IN
import PortStream from 'extension-port-stream';
import { ethErrors } from 'eth-rpc-errors';
@ -18,9 +21,6 @@ import {
ENVIRONMENT_TYPE_FULLSCREEN,
EXTENSION_MESSAGES,
PLATFORM_FIREFOX,
///: BEGIN:ONLY_INCLUDE_IN(snaps)
MESSAGE_TYPE,
///: END:ONLY_INCLUDE_IN
} from '../../shared/constants/app';
import {
REJECT_NOTIFICATION_CLOSE,
@ -677,7 +677,9 @@ export function setupController(
// User Interface setup
//
updateBadge();
controller.txController.initApprovals().then(() => {
updateBadge();
});
controller.txController.on(
METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE,
updateBadge,
@ -764,11 +766,11 @@ export function setupController(
({ id, type }) => {
switch (type) {
///: BEGIN:ONLY_INCLUDE_IN(snaps)
case MESSAGE_TYPE.SNAP_DIALOG_ALERT:
case MESSAGE_TYPE.SNAP_DIALOG_PROMPT:
case ApprovalType.SnapDialogAlert:
case ApprovalType.SnapDialogPrompt:
controller.approvalController.accept(id, null);
break;
case MESSAGE_TYPE.SNAP_DIALOG_CONFIRMATION:
case ApprovalType.SnapDialogConfirmation:
controller.approvalController.accept(id, false);
break;
///: END:ONLY_INCLUDE_IN

View File

@ -2,6 +2,7 @@ import EventEmitter from 'events';
import { ObservableStore } from '@metamask/obs-store';
import { v4 as uuid } from 'uuid';
import log from 'loglevel';
import { ApprovalType } from '@metamask/controller-utils';
import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller';
import { MINUTE } from '../../../shared/constants/time';
import { AUTO_LOCK_TIMEOUT_ALARM } from '../../../shared/constants/alarms';
@ -13,8 +14,6 @@ import {
ORIGIN_METAMASK,
} from '../../../shared/constants/app';
const APPROVAL_REQUEST_TYPE = 'unlock';
export default class AppStateController extends EventEmitter {
/**
* @param {object} opts
@ -375,6 +374,25 @@ export default class AppStateController extends EventEmitter {
this.store.updateState({ usedNetworks });
}
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
/**
* Set the interactive replacement token with a url and the old refresh token
*
* @param {object} opts
* @param opts.url
* @param opts.oldRefreshToken
* @returns {void}
*/
showInteractiveReplacementTokenBanner({ url, oldRefreshToken }) {
this.store.updateState({
interactiveReplacementToken: {
url,
oldRefreshToken,
},
});
}
///: END:ONLY_INCLUDE_IN
/**
* A setter for the currentPopupId which indicates the id of popup window that's currently active
*
@ -408,7 +426,7 @@ export default class AppStateController extends EventEmitter {
{
id: this._approvalRequestId,
origin: ORIGIN_METAMASK,
type: APPROVAL_REQUEST_TYPE,
type: ApprovalType.Unlock,
},
true,
)

View File

@ -13,7 +13,7 @@ import { convertHexToDecimal } from '@metamask/controller-utils';
import { NETWORK_TYPES } from '../../../shared/constants/network';
import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils';
import DetectTokensController from './detect-tokens';
import { NetworkController, NetworkControllerEventType } from './network';
import { NetworkController } from './network';
import PreferencesController from './preferences';
describe('DetectTokensController', function () {
@ -248,7 +248,7 @@ describe('DetectTokensController', function () {
),
onNetworkStateChange: (cb) =>
networkControllerMessenger.subscribe(
NetworkControllerEventType.NetworkDidChange,
'NetworkController:networkDidChange',
() => {
const networkState = network.store.getState();
const modifiedNetworkState = {

View File

@ -625,10 +625,21 @@ export default class MetaMetricsController {
* @returns {MetaMetricsContext}
*/
_buildContext(referrer, page = METAMETRICS_BACKGROUND_PAGE_OBJECT) {
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
const mmiProps = {};
if (this.extension?.runtime?.id) {
mmiProps.extensionId = this.extension.runtime.id;
}
///: END:ONLY_INCLUDE_IN
return {
app: {
name: 'MetaMask Extension',
version: this.version,
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
...mmiProps,
///: END:ONLY_INCLUDE_IN
},
userAgent: window.navigator.userAgent,
page,
@ -658,6 +669,15 @@ export default class MetaMetricsController {
referrer,
environmentType = ENVIRONMENT_TYPE_BACKGROUND,
} = rawPayload;
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
const mmiProps = {};
if (this.extension?.runtime?.id) {
mmiProps.extensionId = this.extension.runtime.id;
}
///: END:ONLY_INCLUDE_IN
return {
event,
messageId: buildUniqueMessageId(rawPayload),
@ -676,6 +696,9 @@ export default class MetaMetricsController {
locale: this.locale,
chain_id: properties?.chain_id ?? this.chainId,
environment_type: environmentType,
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
...mmiProps,
///: END:ONLY_INCLUDE_IN
},
context: this._buildContext(referrer, page),
};
@ -689,6 +712,13 @@ export default class MetaMetricsController {
* @returns {MetaMetricsTraits | null} traits that have changed since last update
*/
_buildUserTraitsObject(metamaskState) {
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
const mmiAccountAddress =
metamaskState.custodyAccountDetails &&
Object.keys(metamaskState.custodyAccountDetails).length
? Object.keys(metamaskState.custodyAccountDetails)[0]
: null;
///: END:ONLY_INCLUDE_IN
const { traits, previousUserTraits } = this.store.getState();
/** @type {MetaMetricsTraits} */
const currentTraits = {
@ -728,6 +758,11 @@ export default class MetaMetricsController {
[MetaMetricsUserTrait.DesktopEnabled]:
metamaskState.desktopEnabled || false,
///: END:ONLY_INCLUDE_IN
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
[MetaMetricsUserTrait.MmiExtensionId]: this.extension?.runtime?.id,
[MetaMetricsUserTrait.MmiAccountAddress]: mmiAccountAddress,
[MetaMetricsUserTrait.MmiIsCustodian]: Boolean(mmiAccountAddress),
///: END:ONLY_INCLUDE_IN
[MetaMetricsUserTrait.SecurityProviders]:
metamaskState.transactionSecurityCheckEnabled ? ['opensea'] : [],
};

View File

@ -23,6 +23,14 @@ const FAKE_CHAIN_ID = '0x1338';
const LOCALE = 'en_US';
const TEST_META_METRICS_ID = '0xabc';
const DUMMY_ACTION_ID = 'DUMMY_ACTION_ID';
const MOCK_EXTENSION_ID = 'testid';
const MOCK_EXTENSION = {
runtime: {
id: MOCK_EXTENSION_ID,
setUninstallURL: () => undefined,
},
};
const MOCK_TRAITS = {
test_boolean: true,
@ -39,7 +47,11 @@ const MOCK_INVALID_TRAITS = {
};
const DEFAULT_TEST_CONTEXT = {
app: { name: 'MetaMask Extension', version: VERSION },
app: {
name: 'MetaMask Extension',
version: VERSION,
extensionId: MOCK_EXTENSION_ID,
},
page: METAMETRICS_BACKGROUND_PAGE_OBJECT,
referrer: undefined,
userAgent: window.navigator.userAgent,
@ -56,6 +68,7 @@ const DEFAULT_EVENT_PROPERTIES = {
revenue: undefined,
value: undefined,
currency: undefined,
extensionId: MOCK_EXTENSION_ID,
...DEFAULT_SHARED_PROPERTIES,
};
@ -149,6 +162,7 @@ function getMetaMetricsController({
},
events: {},
},
extension: MOCK_EXTENSION,
});
}
describe('MetaMetricsController', function () {
@ -973,6 +987,11 @@ describe('MetaMetricsController', function () {
[MetaMetricsUserTrait.TokenDetectionEnabled]: true,
[MetaMetricsUserTrait.DesktopEnabled]: false,
[MetaMetricsUserTrait.SecurityProviders]: [],
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
[MetaMetricsUserTrait.MmiExtensionId]: 'testid',
[MetaMetricsUserTrait.MmiAccountAddress]: null,
[MetaMetricsUserTrait.MmiIsCustodian]: false,
///: END:ONLY_INCLUDE_IN
});
});

File diff suppressed because it is too large Load Diff

View File

@ -82,35 +82,13 @@ type NetworkConfigurationId = string;
*/
type ChainId = Hex;
/**
* The set of event types that NetworkController can publish via its messenger.
*/
export enum NetworkControllerEventType {
/**
* @see {@link NetworkControllerNetworkDidChangeEvent}
*/
NetworkDidChange = 'NetworkController:networkDidChange',
/**
* @see {@link NetworkControllerNetworkWillChangeEvent}
*/
NetworkWillChange = 'NetworkController:networkWillChange',
/**
* @see {@link NetworkControllerInfuraIsBlockedEvent}
*/
InfuraIsBlocked = 'NetworkController:infuraIsBlocked',
/**
* @see {@link NetworkControllerInfuraIsUnblockedEvent}
*/
InfuraIsUnblocked = 'NetworkController:infuraIsUnblocked',
}
/**
* `networkWillChange` is published when the current network is about to be
* switched, but the new provider has not been created and no state changes have
* occurred yet.
*/
export type NetworkControllerNetworkWillChangeEvent = {
type: NetworkControllerEventType.NetworkWillChange;
type: 'NetworkController:networkWillChange';
payload: [];
};
@ -119,7 +97,7 @@ export type NetworkControllerNetworkWillChangeEvent = {
* switched network (but before the network has been confirmed to be available).
*/
export type NetworkControllerNetworkDidChangeEvent = {
type: NetworkControllerEventType.NetworkDidChange;
type: 'NetworkController:networkDidChange';
payload: [];
};
@ -129,7 +107,7 @@ export type NetworkControllerNetworkDidChangeEvent = {
* location.
*/
export type NetworkControllerInfuraIsBlockedEvent = {
type: NetworkControllerEventType.InfuraIsBlocked;
type: 'NetworkController:infuraIsBlocked';
payload: [];
};
@ -139,7 +117,7 @@ export type NetworkControllerInfuraIsBlockedEvent = {
* their location, or the network is switched to a non-Infura network.
*/
export type NetworkControllerInfuraIsUnblockedEvent = {
type: NetworkControllerEventType.InfuraIsUnblocked;
type: 'NetworkController:infuraIsUnblocked';
payload: [];
};
@ -159,8 +137,8 @@ export type NetworkControllerMessenger = RestrictedControllerMessenger<
typeof name,
never,
NetworkControllerEvent,
never,
NetworkControllerEventType
string,
string
>;
/**
@ -611,14 +589,11 @@ export class NetworkController extends EventEmitter {
const listener = () => {
networkChanged = true;
this.#messenger.unsubscribe(
NetworkControllerEventType.NetworkDidChange,
'NetworkController:networkDidChange',
listener,
);
};
this.#messenger.subscribe(
NetworkControllerEventType.NetworkDidChange,
listener,
);
this.#messenger.subscribe('NetworkController:networkDidChange', listener);
try {
const results = await Promise.all([
@ -630,12 +605,14 @@ export class NetworkController extends EventEmitter {
supportsEIP1559 = results[1];
networkStatus = NetworkStatus.Available;
} catch (error) {
if (isErrorWithCode(error) && isErrorWithMessage(error)) {
if (isErrorWithCode(error)) {
let responseBody;
try {
responseBody = JSON.parse(error.message);
} catch {
// error.message must not be JSON
if (isInfura && isErrorWithMessage(error)) {
try {
responseBody = JSON.parse(error.message);
} catch {
// error.message must not be JSON
}
}
if (
@ -662,10 +639,7 @@ export class NetworkController extends EventEmitter {
// in the process of being called, so we don't need to go further.
return;
}
this.#messenger.unsubscribe(
NetworkControllerEventType.NetworkDidChange,
listener,
);
this.#messenger.unsubscribe('NetworkController:networkDidChange', listener);
this.store.updateState({
networkStatus,
@ -690,15 +664,15 @@ export class NetworkController extends EventEmitter {
if (isInfura) {
if (networkStatus === NetworkStatus.Available) {
this.#messenger.publish(NetworkControllerEventType.InfuraIsUnblocked);
this.#messenger.publish('NetworkController:infuraIsUnblocked');
} else if (networkStatus === NetworkStatus.Blocked) {
this.#messenger.publish(NetworkControllerEventType.InfuraIsBlocked);
this.#messenger.publish('NetworkController:infuraIsBlocked');
}
} else {
// Always publish infuraIsUnblocked regardless of network status to
// prevent consumers from being stuck in a blocked state if they were
// previously connected to an Infura network that was blocked
this.#messenger.publish(NetworkControllerEventType.InfuraIsUnblocked);
this.#messenger.publish('NetworkController:infuraIsUnblocked');
}
}
@ -890,12 +864,12 @@ export class NetworkController extends EventEmitter {
* the new network.
*/
async #switchNetwork(providerConfig: ProviderConfiguration) {
this.#messenger.publish(NetworkControllerEventType.NetworkWillChange);
this.#messenger.publish('NetworkController:networkWillChange');
this.#resetNetworkId();
this.#resetNetworkStatus();
this.#resetNetworkDetails();
this.#configureProvider(providerConfig);
this.#messenger.publish(NetworkControllerEventType.NetworkDidChange);
this.#messenger.publish('NetworkController:networkDidChange');
await this.lookupNetwork();
}

View File

@ -149,7 +149,7 @@ function mockRpcCall({
}
}
/* @ts-expect-error The types for Nock do not include `basePath` in the interface for Nock.Scope. */
const url = nockScope.basePath.includes('infura.io')
const url = new URL(nockScope.basePath).hostname.match(/(\.|^)infura.io$/u)
? `/v3/${MOCK_INFURA_PROJECT_ID}`
: '/';

View File

@ -295,9 +295,8 @@ export function testsForProviderType(providerType: ProviderType) {
// tests on the core side.
{ name: 'net_listening', numberOfParameters: 0 },
// TODO: Methods to add back when we add testing for subscribe middleware
// { name: 'eth_subscribe', numberOfParameters: 1 },
// { name: 'eth_unsubscribe', numberOfParameters: 1 },
{ name: 'eth_subscribe', numberOfParameters: 1 },
{ name: 'eth_unsubscribe', numberOfParameters: 1 },
{ name: 'custom_rpc_method', numberOfParameters: 1 },
{ name: 'net_peerCount', numberOfParameters: 0 },
{ name: 'parity_nextNonce', numberOfParameters: 1 },

View File

@ -1,5 +1,8 @@
import { ObservableStore } from '@metamask/obs-store';
import { normalize as normalizeAddress } from 'eth-sig-util';
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
import { setDashboardCookie } from '@metamask-institutional/portfolio-dashboard';
///: END:ONLY_INCLUDE_IN
import { IPFS_DEFAULT_GATEWAY_URL } from '../../../shared/constants/network';
import { LedgerTransportTypes } from '../../../shared/constants/hardware-wallets';
import { ThemeType } from '../../../shared/constants/preferences';
@ -69,12 +72,25 @@ export default class PreferencesController {
...opts.initState,
};
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
initState.useTokenDetection = Boolean(process.env.TOKEN_DETECTION_V2);
///: END:ONLY_INCLUDE_IN
this.network = opts.network;
this._onInfuraIsBlocked = opts.onInfuraIsBlocked;
this._onInfuraIsUnblocked = opts.onInfuraIsUnblocked;
this.store = new ObservableStore(initState);
this.store.setMaxListeners(13);
this.tokenListController = opts.tokenListController;
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
this.handleMmiPortfolio = opts.handleMmiPortfolio;
if (!process.env.IN_TEST) {
this.mmiConfigurationStore = opts.mmiConfigurationStore.getState();
}
///: END:ONLY_INCLUDE_IN
this._subscribeToInfuraAvailability();
global.setPreference = (key, value) => {
@ -245,6 +261,10 @@ export default class PreferencesController {
return ids;
}, {});
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
this.prepareMmiPortfolio();
///: END:ONLY_INCLUDE_IN
this.store.updateState({ identities });
}
@ -269,6 +289,11 @@ export default class PreferencesController {
const [selected] = Object.keys(identities);
this.setSelectedAddress(selected);
}
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
this.prepareMmiPortfolio();
///: END:ONLY_INCLUDE_IN
return address;
}
@ -325,6 +350,10 @@ export default class PreferencesController {
this.store.updateState({ identities, lostIdentities });
this.addAddresses(addresses);
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
this.prepareMmiPortfolio();
///: END:ONLY_INCLUDE_IN
// If the selected account is no longer valid,
// select an arbitrary other account:
let selected = this.getSelectedAddress();
@ -505,6 +534,21 @@ export default class PreferencesController {
return this.store.getState().disabledRpcMethodPreferences;
}
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
async prepareMmiPortfolio() {
if (!process.env.IN_TEST) {
try {
const mmiDashboardData = await this.handleMmiPortfolio();
const cookieSetUrls =
this.mmiConfigurationStore.mmiConfiguration?.portfolio?.cookieSetUrls;
setDashboardCookie(mmiDashboardData, cookieSetUrls);
} catch (error) {
console.error(error);
}
}
}
///: END:ONLY_INCLUDE_IN
//
// PRIVATE METHODS
//

View File

@ -5,6 +5,7 @@ import EthQuery from 'ethjs-query';
import { ethErrors } from 'eth-rpc-errors';
import { Common, Hardfork } from '@ethereumjs/common';
import { TransactionFactory } from '@ethereumjs/tx';
import { ApprovalType } from '@metamask/controller-utils';
import NonceTracker from 'nonce-tracker';
import log from 'loglevel';
import BigNumber from 'bignumber.js';
@ -51,10 +52,7 @@ import {
determineTransactionType,
isEIP1559Transaction,
} from '../../../../shared/modules/transaction.utils';
import {
ORIGIN_METAMASK,
MESSAGE_TYPE,
} from '../../../../shared/constants/app';
import { ORIGIN_METAMASK } from '../../../../shared/constants/app';
import {
calcGasTotal,
getSwapsTokensReceivedFromTxMeta,
@ -396,6 +394,22 @@ export default class TransactionController extends EventEmitter {
});
}
/**
* Creates approvals for all unapproved transactions in the txStateManager.
*
* @returns {Promise<void>}
*/
async initApprovals() {
const unapprovedTxs = this.txStateManager.getUnapprovedTxList();
return Promise.all(
Object.values(unapprovedTxs).map((txMeta) =>
this._requestApproval(txMeta, {
shouldShowRequest: false,
}),
),
);
}
// ====================================================================================================================================================
/**
@ -2648,13 +2662,16 @@ export default class TransactionController extends EventEmitter {
);
}
_requestApproval(txMeta) {
async _requestApproval(
txMeta,
{ shouldShowRequest } = { shouldShowRequest: true },
) {
const id = this._getApprovalId(txMeta);
const { origin } = txMeta;
const type = MESSAGE_TYPE.TRANSACTION;
const type = ApprovalType.Transaction;
const requestData = { txId: txMeta.id };
this.messagingSystem
return this.messagingSystem
.call(
'ApprovalController:addRequest',
{
@ -2663,7 +2680,7 @@ export default class TransactionController extends EventEmitter {
type,
requestData,
},
true,
shouldShowRequest,
)
.catch(() => {
// Intentionally ignored as promise not currently used

View File

@ -3,6 +3,7 @@ import EventEmitter from 'events';
import { toBuffer } from 'ethereumjs-util';
import { TransactionFactory } from '@ethereumjs/tx';
import { ObservableStore } from '@metamask/obs-store';
import { ApprovalType } from '@metamask/controller-utils';
import sinon from 'sinon';
import {
@ -29,10 +30,7 @@ import {
GasRecommendations,
} from '../../../../shared/constants/gas';
import { METAMASK_CONTROLLER_EVENTS } from '../../metamask-controller';
import {
MESSAGE_TYPE,
ORIGIN_METAMASK,
} from '../../../../shared/constants/app';
import { ORIGIN_METAMASK } from '../../../../shared/constants/app';
import { NetworkStatus } from '../../../../shared/constants/network';
import { TRANSACTION_ENVELOPE_TYPE_NAMES } from '../../../../shared/lib/transactions-controller-utils';
import TransactionController from '.';
@ -513,7 +511,7 @@ describe('Transaction Controller', function () {
id: String(txMeta.id),
origin: ORIGIN_METAMASK,
requestData: { txId: txMeta.id },
type: MESSAGE_TYPE.TRANSACTION,
type: ApprovalType.Transaction,
},
true, // Show popup
]);
@ -551,7 +549,7 @@ describe('Transaction Controller', function () {
id: String(secondTxMeta.id),
origin: ORIGIN_METAMASK,
requestData: { txId: secondTxMeta.id },
type: MESSAGE_TYPE.TRANSACTION,
type: ApprovalType.Transaction,
},
true, // Show popup
]);
@ -2994,4 +2992,58 @@ describe('Transaction Controller', function () {
assert.equal(result.type, TransactionType.simpleSend);
});
});
describe('initApprovals', function () {
it('adds unapprovedTxs as approvals', async function () {
const firstTxId = '1';
txController.addTransaction(
{
id: firstTxId,
origin: ORIGIN_METAMASK,
status: TransactionStatus.unapproved,
metamaskNetworkId: currentNetworkId,
txParams: {
to: VALID_ADDRESS,
from: VALID_ADDRESS_TWO,
},
},
noop,
);
const secondTxId = '2';
txController.addTransaction(
{
id: secondTxId,
origin: ORIGIN_METAMASK,
status: TransactionStatus.unapproved,
metamaskNetworkId: currentNetworkId,
txParams: {
to: VALID_ADDRESS,
from: VALID_ADDRESS_TWO,
},
},
noop,
);
await txController.initApprovals();
assert.deepEqual(messengerMock.call.getCall(0).args, [
'ApprovalController:addRequest',
{
id: firstTxId,
origin: ORIGIN_METAMASK,
requestData: { txId: firstTxId },
type: ApprovalType.Transaction,
},
false,
]);
assert.deepEqual(messengerMock.call.getCall(1).args, [
'ApprovalController:addRequest',
{
id: secondTxId,
origin: ORIGIN_METAMASK,
requestData: { txId: secondTxId },
type: ApprovalType.Transaction,
},
false,
]);
});
});
});

View File

@ -1,6 +1,7 @@
import { ethErrors, errorCodes } from 'eth-rpc-errors';
import validUrl from 'valid-url';
import { omit } from 'lodash';
import { ApprovalType } from '@metamask/controller-utils';
import {
MESSAGE_TYPE,
UNKNOWN_TICKER_SYMBOL,
@ -158,7 +159,7 @@ async function addEthereumChainHandler(
try {
await requestUserApproval({
origin,
type: MESSAGE_TYPE.SWITCH_ETHEREUM_CHAIN,
type: ApprovalType.SwitchEthereumChain,
requestData: {
rpcUrl: existingNetwork.rpcUrl,
chainId: existingNetwork.chainId,
@ -244,7 +245,7 @@ async function addEthereumChainHandler(
try {
await requestUserApproval({
origin,
type: MESSAGE_TYPE.ADD_ETHEREUM_CHAIN,
type: ApprovalType.AddEthereumChain,
requestData: {
chainId: _chainId,
rpcPrefs: { blockExplorerUrl: firstValidBlockExplorerUrl },
@ -275,7 +276,7 @@ async function addEthereumChainHandler(
try {
await requestUserApproval({
origin,
type: MESSAGE_TYPE.SWITCH_ETHEREUM_CHAIN,
type: ApprovalType.SwitchEthereumChain,
requestData: {
rpcUrl: firstValidRPCUrl,
chainId: _chainId,

View File

@ -1,5 +1,6 @@
import { ethErrors } from 'eth-rpc-errors';
import { omit } from 'lodash';
import { ApprovalType } from '@metamask/controller-utils';
import { MESSAGE_TYPE } from '../../../../../shared/constants/app';
import {
CHAIN_ID_TO_TYPE_MAP,
@ -109,7 +110,7 @@ async function switchEthereumChainHandler(
try {
const approvedRequestData = await requestUserApproval({
origin,
type: MESSAGE_TYPE.SWITCH_ETHEREUM_CHAIN,
type: ApprovalType.SwitchEthereumChain,
requestData,
});
if (

View File

@ -49,6 +49,7 @@ import {
SubjectType,
} from '@metamask/subject-metadata-controller';
///: BEGIN:ONLY_INCLUDE_IN(snaps)
import { encrypt, decrypt } from '@metamask/browser-passworder';
import { RateLimitController } from '@metamask/rate-limit-controller';
import { NotificationController } from '@metamask/notification-controller';
///: END:ONLY_INCLUDE_IN
@ -139,10 +140,7 @@ import createTabIdMiddleware from './lib/createTabIdMiddleware';
import createOnboardingMiddleware from './lib/createOnboardingMiddleware';
import { setupMultiplex } from './lib/stream-utils';
import EnsController from './controllers/ens';
import {
NetworkController,
NetworkControllerEventType,
} from './controllers/network';
import { NetworkController } from './controllers/network';
import PreferencesController from './controllers/preferences';
import AppStateController from './controllers/app-state';
import CachedBalancesController from './controllers/cached-balances';
@ -268,7 +266,12 @@ export default class MetamaskController extends EventEmitter {
const networkControllerMessenger = this.controllerMessenger.getRestricted({
name: 'NetworkController',
allowedEvents: Object.values(NetworkControllerEventType),
allowedEvents: [
'NetworkController:networkWillChange',
'NetworkController:networkDidChange',
'NetworkController:infuraIsBlocked',
'NetworkController:infuraIsUnblocked',
],
});
this.networkController = new NetworkController({
messenger: networkControllerMessenger,
@ -315,11 +318,11 @@ export default class MetamaskController extends EventEmitter {
initLangCode: opts.initLangCode,
onInfuraIsBlocked: networkControllerMessenger.subscribe.bind(
networkControllerMessenger,
NetworkControllerEventType.InfuraIsBlocked,
'NetworkController:infuraIsBlocked',
),
onInfuraIsUnblocked: networkControllerMessenger.subscribe.bind(
networkControllerMessenger,
NetworkControllerEventType.InfuraIsUnblocked,
'NetworkController:infuraIsUnblocked',
),
tokenListController: this.tokenListController,
provider: this.provider,
@ -365,7 +368,7 @@ export default class MetamaskController extends EventEmitter {
// network provider by one update.
onNetworkStateChange: (cb) =>
networkControllerMessenger.subscribe(
NetworkControllerEventType.NetworkDidChange,
'NetworkController:networkDidChange',
() => {
const networkState = this.networkController.store.getState();
const modifiedNetworkState = {
@ -476,7 +479,7 @@ export default class MetamaskController extends EventEmitter {
preferencesStore: this.preferencesController.store,
onNetworkDidChange: networkControllerMessenger.subscribe.bind(
networkControllerMessenger,
NetworkControllerEventType.NetworkDidChange,
'NetworkController:networkDidChange',
),
getNetworkIdentifier: () => {
const { type, rpcUrl } =
@ -515,7 +518,7 @@ export default class MetamaskController extends EventEmitter {
// onNetworkDidChange
onNetworkStateChange: networkControllerMessenger.subscribe.bind(
networkControllerMessenger,
NetworkControllerEventType.NetworkDidChange,
'NetworkController:networkDidChange',
),
getCurrentNetworkEIP1559Compatibility:
this.networkController.getEIP1559Compatibility.bind(
@ -641,7 +644,7 @@ export default class MetamaskController extends EventEmitter {
this.networkController.store.getState().providerConfig.chainId,
onNetworkDidChange: networkControllerMessenger.subscribe.bind(
networkControllerMessenger,
NetworkControllerEventType.NetworkDidChange,
'NetworkController:networkDidChange',
),
});
@ -653,7 +656,7 @@ export default class MetamaskController extends EventEmitter {
blockTracker: this.blockTracker,
onNetworkDidChange: networkControllerMessenger.subscribe.bind(
networkControllerMessenger,
NetworkControllerEventType.NetworkDidChange,
'NetworkController:networkDidChange',
),
getCurrentChainId: () =>
this.networkController.store.getState().providerConfig.chainId,
@ -754,6 +757,7 @@ export default class MetamaskController extends EventEmitter {
`${this.approvalController.name}:rejectRequest`,
`SnapController:getPermitted`,
`SnapController:install`,
`SubjectMetadataController:getSubjectMetadata`,
],
}),
state: initState.PermissionController,
@ -813,7 +817,7 @@ export default class MetamaskController extends EventEmitter {
///: BEGIN:ONLY_INCLUDE_IN(snaps)
const snapExecutionServiceArgs = {
iframeUrl: new URL('https://execution.metamask.io/0.15.1/index.html'),
iframeUrl: new URL(process.env.IFRAME_EXECUTION_ENVIRONMENT_URL),
messenger: this.controllerMessenger.getRestricted({
name: 'ExecutionService',
}),
@ -1149,7 +1153,7 @@ export default class MetamaskController extends EventEmitter {
});
networkControllerMessenger.subscribe(
NetworkControllerEventType.NetworkDidChange,
'NetworkController:networkDidChange',
async () => {
const { ticker } =
this.networkController.store.getState().providerConfig;
@ -1210,18 +1214,23 @@ export default class MetamaskController extends EventEmitter {
?.disabledRpcMethodPreferences?.eth_sign,
getAllState: this.getState.bind(this),
securityProviderRequest: this.securityProviderRequest.bind(this),
getCurrentChainId: () =>
this.networkController.store.getState().providerConfig.chainId,
});
this.signatureController.hub.on('cancelWithReason', (message, reason) => {
this.metaMetricsController.trackEvent({
event: reason,
category: MetaMetricsEventCategory.Transactions,
properties: {
action: 'Sign Request',
type: message.type,
},
});
});
this.signatureController.hub.on(
'cancelWithReason',
({ message, reason }) => {
this.metaMetricsController.trackEvent({
event: reason,
category: MetaMetricsEventCategory.Transactions,
properties: {
action: 'Sign Request',
type: message.type,
},
});
},
);
this.swapsController = new SwapsController({
getBufferedGasLimit: this.txController.txGasUtil.getBufferedGasLimit.bind(
@ -1272,7 +1281,7 @@ export default class MetamaskController extends EventEmitter {
// ensure accountTracker updates balances after network change
networkControllerMessenger.subscribe(
NetworkControllerEventType.NetworkDidChange,
'NetworkController:networkDidChange',
() => {
this.accountTracker._updateAccounts();
},
@ -1280,7 +1289,7 @@ export default class MetamaskController extends EventEmitter {
// clear unapproved transactions and messages when the network will change
networkControllerMessenger.subscribe(
NetworkControllerEventType.NetworkWillChange,
'NetworkController:networkWillChange',
() => {
this.txController.txStateManager.clearUnapprovedTxs();
this.encryptionPublicKeyController.clearUnapproved();
@ -1570,6 +1579,8 @@ export default class MetamaskController extends EventEmitter {
return {
...buildSnapEndowmentSpecifications(),
...buildSnapRestrictedMethodSpecifications({
encrypt,
decrypt,
clearSnapState: this.controllerMessenger.call.bind(
this.controllerMessenger,
'SnapController:clearSnapState',

View File

@ -50,6 +50,7 @@ buildTypes:
- SEGMENT_FLASK_WRITE_KEY
- ALLOW_LOCAL_SNAPS: true
- REQUIRE_SNAPS_ALLOWLIST: false
- IFRAME_EXECUTION_ENVIRONMENT_URL: https://execution.metamask.io/0.16.0-flask.1/index.html
- SUPPORT_LINK: https://metamask-flask.zendesk.com/hc
- SUPPORT_REQUEST_LINK: https://metamask-flask.zendesk.com/hc/en-us/requests/new
- INFURA_ENV_KEY_REF: INFURA_FLASK_PROJECT_ID
@ -67,6 +68,7 @@ buildTypes:
- SEGMENT_FLASK_WRITE_KEY
- ALLOW_LOCAL_SNAPS: true
- REQUIRE_SNAPS_ALLOWLIST: false
- IFRAME_EXECUTION_ENVIRONMENT_URL: https://execution.metamask.io/0.16.0-flask.1/index.html
- SUPPORT_LINK: https://metamask-flask.zendesk.com/hc
- SUPPORT_REQUEST_LINK: https://metamask-flask.zendesk.com/hc/en-us/requests/new
- INFURA_ENV_KEY_REF: INFURA_FLASK_PROJECT_ID
@ -101,6 +103,7 @@ features:
- ALLOW_LOCAL_SNAPS
# Whether to verify that a snap can be installed using an allow list
- REQUIRE_SNAPS_ALLOWLIST
- IFRAME_EXECUTION_ENVIRONMENT_URL
assets:
- ./{app,shared,ui}/**/snaps/**
desktop:
@ -127,7 +130,7 @@ features:
assets:
- src: ./app/build-types/mmi/images/
dest: images
- ./{app,shared,ui}/**/mmi/**
- ./{app,shared,ui}/**/institutional/**
build-flask:
assets:
- src: ./app/build-types/flask/images/
@ -197,8 +200,6 @@ env:
# Also see DEBUG and NODE_DEBUG
- METAMASK_DEBUG: false
# Modified in <root>/development/build/scripts.js:@setEnvironmentVariables
- ICON_NAMES
# Modified in <root>/development/build/scripts.js:@setEnvironmentVariables
- IN_TEST
# Modified in <root>/development/build/scripts.js:@setEnvironmentVariables
- METAMASK_ENVIRONMENT
@ -213,6 +214,8 @@ env:
# if it's not inside process.env
# Also see DEBUG and METAMASK_DEBUG
- NODE_DEBUG: ''
# Used by react-devtools-core
- EDITOR_URL: ''
###
# Meta variables

View File

@ -6,10 +6,10 @@
// subset of files to check against these targets.
module.exports = {
global: {
lines: 70.26,
branches: 57.91,
statements: 69.59,
functions: 62.97,
lines: 71.15,
branches: 59.17,
statements: 70.6,
functions: 63.82,
},
transforms: {
branches: 100,

View File

@ -33,7 +33,6 @@ const bifyModuleGroups = require('bify-module-groups');
const phishingWarningManifest = require('@metamask/phishing-warning/package.json');
const { streamFlatMap } = require('../stream-flat-map');
const { generateIconNames } = require('../generate-icon-names');
const { BUILD_TARGETS, ENVIRONMENT } = require('./constants');
const { getConfig } = require('./config');
const {
@ -1182,10 +1181,8 @@ async function setEnvironmentVariables({
}) {
const devMode = isDevBuild(buildTarget);
const testing = isTestBuild(buildTarget);
const iconNames = await generateIconNames();
variables.set({
ICON_NAMES: iconNames,
IN_TEST: testing,
INFURA_PROJECT_ID: getInfuraProjectId({
buildType,

View File

@ -1,42 +0,0 @@
/**
* Generate icon names
*
* Reads all the icon svg files in app/images/icons
* and returns an object of icon name key value pairs
* stored in the environment variable ICON_NAMES
* Used with the Icon component in ./ui/components/component-library/icon/icon.js
*/
const fs = require('fs');
const path = require('path');
const SVG_ICONS_FOLDER = './app/images/icons';
const ASSET_EXT = '.svg';
const getIconNameKebabCase = (fileName) => path.basename(fileName, ASSET_EXT);
const getIconNameInSnakeCase = (fileName) =>
path.basename(fileName, ASSET_EXT).replace(/-/gu, '_').toUpperCase();
const generateIconNames = () => {
const iconNames = {};
const svgIconsFolderPath = path.join(__dirname, `../${SVG_ICONS_FOLDER}`);
const fileList = fs.readdirSync(svgIconsFolderPath);
const svgIconsFileList = fileList.filter(
(fileName) => path.extname(fileName) === ASSET_EXT,
);
svgIconsFileList.forEach(
(fileName) =>
(iconNames[getIconNameInSnakeCase(fileName)] =
getIconNameKebabCase(fileName)),
);
const iconNamesStringified = JSON.stringify(iconNames);
return iconNamesStringified;
};
module.exports = { generateIconNames };

View File

@ -1,12 +1,24 @@
#! /bin/bash
validate-number(){
re='^[0-9]+$'
if [[ ! $1 =~ $re ]]; then
echo "Error: The value must be a number." >&2
exit 1
fi
}
g-migration() {
[[ -z "$1" ]] && { echo "Migration version is required!" ; exit 1; }
local vnum=$1
validate-number "$vnum"
if (($1 < 100)); then
vnum=0$1
fi
touch app/scripts/migrations/"$vnum".js
cp app/scripts/migrations/template.js app/scripts/migrations/"$vnum".js
touch app/scripts/migrations/"$vnum".ts
cp app/scripts/migrations/template.ts app/scripts/migrations/"$vnum".ts
touch app/scripts/migrations/"$vnum".test.js
cp app/scripts/migrations/template.test.js app/scripts/migrations/"$vnum".test.js

View File

@ -29,7 +29,11 @@ class Variables {
assert(
value !== DeclaredOnly,
new TypeError(
`Tried to access a declared, but not defined environmental variable "${key}"`,
`Tried to access a declared, but not defined environmental variable "${key}"
\tWhy am I seeing this: "${key}" is declared in builds.yml, but had no actual value when we tried loading it.
\tHow do I fix this: You could provide a default value for the variable in builds.yml under "env" property and commit to git. For example:
\t\tenv:
\t\t - ${key}: ''`,
),
);
return value;
@ -46,7 +50,9 @@ class Variables {
assert(
this.isDeclared(key),
new TypeError(
`Tried to access an environmental variable "${key}" that wasn't declared in builds.yml`,
`Tried to access an environmental variable "${key}" that wasn't declared in builds.yml
\tWhy am I seeing this: We've made use of new variables be explicit to keep track of all of them in one place
\tHow do I fix this: Adding your variable in builds.yml under "env" property and committing to git will fix this`,
),
);
return this.#definitions.get(key);

View File

@ -32,11 +32,7 @@ module.exports = {
// TODO: enable resetMocks
// resetMocks: true,
restoreMocks: true,
setupFiles: [
'<rootDir>/test/setup.js',
'<rootDir>/test/env.js',
'<rootDir>/test/jest/env.js', // jest specific env vars that break mocha tests
],
setupFiles: ['<rootDir>/test/setup.js', '<rootDir>/test/env.js'],
setupFilesAfterEnv: ['<rootDir>/test/jest/setup.js'],
testMatch: [
'<rootDir>/app/scripts/constants/error-utils.test.js',

View File

@ -5,6 +5,11 @@
"regeneratorRuntime": "write"
}
},
"@babel/runtime>regenerator-runtime": {
"globals": {
"regeneratorRuntime": "write"
}
},
"@download/blockies": {
"globals": {
"document.createElement": true
@ -868,6 +873,20 @@
"immer": true
}
},
"@metamask/browser-passworder": {
"globals": {
"btoa": true,
"crypto.getRandomValues": true,
"crypto.subtle.decrypt": true,
"crypto.subtle.deriveKey": true,
"crypto.subtle.encrypt": true,
"crypto.subtle.exportKey": true,
"crypto.subtle.importKey": true
},
"packages": {
"browserify>buffer": true
}
},
"@metamask/controller-utils": {
"globals": {
"URL": true,
@ -998,11 +1017,11 @@
},
"@metamask/eth-keyring-controller": {
"packages": {
"@metamask/browser-passworder": true,
"@metamask/eth-keyring-controller>@metamask/eth-hd-keyring": true,
"@metamask/eth-keyring-controller>@metamask/eth-simple-keyring": true,
"@metamask/eth-keyring-controller>obs-store": true,
"@metamask/eth-trezor-keyring>@metamask/eth-sig-util": true,
"@metamask/rpc-methods>@metamask/browser-passworder": true,
"browserify>events": true
}
},
@ -1128,8 +1147,8 @@
"@metamask/eth-token-tracker>deep-equal>is-arguments": true,
"@metamask/eth-token-tracker>deep-equal>is-date-object": true,
"@ngraveio/bc-ur>assert>object-is": true,
"@storybook/api>telejson>is-regex": true,
"globalthis>define-properties>object-keys": true,
"string.prototype.matchall>es-abstract>is-regex": true,
"string.prototype.matchall>regexp.prototype.flags": true
}
},
@ -1610,20 +1629,6 @@
"crypto.getRandomValues": true
}
},
"@metamask/rpc-methods>@metamask/browser-passworder": {
"globals": {
"btoa": true,
"crypto.getRandomValues": true,
"crypto.subtle.decrypt": true,
"crypto.subtle.deriveKey": true,
"crypto.subtle.encrypt": true,
"crypto.subtle.exportKey": true,
"crypto.subtle.importKey": true
},
"packages": {
"browserify>buffer": true
}
},
"@metamask/rpc-methods>nanoid": {
"globals": {
"crypto.getRandomValues": true
@ -1653,25 +1658,13 @@
"packages": {
"@metamask/base-controller": true,
"@metamask/controller-utils": true,
"@metamask/signature-controller>@metamask/message-manager": true,
"@metamask/message-manager": true,
"browserify>buffer": true,
"browserify>events": true,
"eth-rpc-errors": true,
"ethereumjs-util": true
}
},
"@metamask/signature-controller>@metamask/message-manager": {
"packages": {
"@metamask/base-controller": true,
"@metamask/controller-utils": true,
"@metamask/message-manager>jsonschema": true,
"browserify>buffer": true,
"browserify>events": true,
"eth-sig-util": true,
"ethereumjs-util": true,
"uuid": true
}
},
"@metamask/smart-transactions-controller": {
"globals": {
"URLSearchParams": true,
@ -1964,24 +1957,6 @@
"define": true
}
},
"@storybook/api>regenerator-runtime": {
"globals": {
"regeneratorRuntime": "write"
}
},
"@storybook/api>telejson>is-regex": {
"packages": {
"koa>is-generator-function>has-tostringtag": true,
"string.prototype.matchall>call-bind": true
}
},
"@storybook/api>util-deprecate": {
"globals": {
"console.trace": true,
"console.warn": true,
"localStorage": true
}
},
"@truffle/codec": {
"packages": {
"@truffle/codec>@truffle/abi-utils": true,
@ -2078,16 +2053,10 @@
},
"@truffle/codec>@truffle/abi-utils>change-case>pascal-case": {
"packages": {
"@truffle/codec>@truffle/abi-utils>change-case>pascal-case>camel-case": true,
"@truffle/codec>@truffle/abi-utils>change-case>camel-case": true,
"@truffle/codec>@truffle/abi-utils>change-case>upper-case-first": true
}
},
"@truffle/codec>@truffle/abi-utils>change-case>pascal-case>camel-case": {
"packages": {
"@truffle/codec>@truffle/abi-utils>change-case>no-case": true,
"@truffle/codec>@truffle/abi-utils>change-case>upper-case": true
}
},
"@truffle/codec>@truffle/abi-utils>change-case>path-case": {
"packages": {
"@truffle/codec>@truffle/abi-utils>change-case>no-case": true
@ -2194,13 +2163,8 @@
"console.error": true
},
"packages": {
"@truffle/codec>semver>lru-cache": true,
"browserify>process": true
}
},
"@truffle/codec>semver>lru-cache": {
"packages": {
"semver>lru-cache>yallist": true
"browserify>process": true,
"semver>lru-cache": true
}
},
"@truffle/codec>web3-utils": {
@ -2258,9 +2222,9 @@
"@truffle/codec": true,
"@truffle/codec>@truffle/abi-utils": true,
"@truffle/codec>@truffle/compile-common": true,
"@truffle/codec>big.js": true,
"@truffle/codec>web3-utils": true,
"@truffle/decoder>@truffle/encoder>@ensdomains/ensjs": true,
"@truffle/decoder>@truffle/encoder>big.js": true,
"@truffle/decoder>@truffle/encoder>bignumber.js": true,
"lodash": true,
"nock>debug": true
@ -2437,11 +2401,6 @@
"browserify>process": true
}
},
"@truffle/decoder>@truffle/encoder>big.js": {
"globals": {
"define": true
}
},
"@truffle/decoder>@truffle/encoder>bignumber.js": {
"globals": {
"crypto": true,
@ -2471,7 +2430,7 @@
},
"@truffle/decoder>@truffle/source-map-utils>node-interval-tree": {
"packages": {
"@storybook/addon-a11y>react-sizeme>shallowequal": true
"@truffle/decoder>@truffle/source-map-utils>node-interval-tree>shallowequal": true
}
},
"@truffle/decoder>bn.js": {
@ -3304,13 +3263,13 @@
},
"ethereumjs-util>create-hash>md5.js>hash-base>readable-stream": {
"packages": {
"@storybook/api>util-deprecate": true,
"browserify>browser-resolve": true,
"browserify>buffer": true,
"browserify>events": true,
"browserify>process": true,
"browserify>string_decoder": true,
"pumpify>inherits": true
"pumpify>inherits": true,
"readable-stream>util-deprecate": true
}
},
"ethereumjs-util>create-hash>ripemd160": {
@ -3357,13 +3316,13 @@
},
"ethereumjs-util>ethereum-cryptography>keccak>readable-stream": {
"packages": {
"@storybook/api>util-deprecate": true,
"browserify>browser-resolve": true,
"browserify>buffer": true,
"browserify>events": true,
"browserify>process": true,
"browserify>string_decoder": true,
"pumpify>inherits": true
"pumpify>inherits": true,
"readable-stream>util-deprecate": true
}
},
"ethereumjs-util>ethereum-cryptography>scrypt-js": {
@ -3538,7 +3497,7 @@
"ethjs-query>babel-runtime": {
"packages": {
"@babel/runtime": true,
"@storybook/api>regenerator-runtime": true,
"@babel/runtime>regenerator-runtime": true,
"ethjs-query>babel-runtime>core-js": true
}
},
@ -3922,6 +3881,64 @@
"setTimeout": true
}
},
"react-focus-lock": {
"globals": {
"addEventListener": true,
"console.error": true,
"console.warn": true,
"document": true,
"removeEventListener": true,
"setTimeout": true
},
"packages": {
"@babel/runtime": true,
"prop-types": true,
"react": true,
"react-focus-lock>focus-lock": true,
"react-focus-lock>react-clientside-effect": true,
"react-focus-lock>use-callback-ref": true,
"react-focus-lock>use-sidecar": true
}
},
"react-focus-lock>focus-lock": {
"globals": {
"HTMLIFrameElement": true,
"Node.DOCUMENT_FRAGMENT_NODE": true,
"Node.DOCUMENT_NODE": true,
"Node.DOCUMENT_POSITION_CONTAINED_BY": true,
"Node.DOCUMENT_POSITION_CONTAINS": true,
"Node.ELEMENT_NODE": true,
"console.error": true,
"console.warn": true,
"document": true,
"getComputedStyle": true,
"setTimeout": true
},
"packages": {
"wait-on>rxjs>tslib": true
}
},
"react-focus-lock>react-clientside-effect": {
"packages": {
"@babel/runtime": true,
"react": true
}
},
"react-focus-lock>use-callback-ref": {
"packages": {
"react": true
}
},
"react-focus-lock>use-sidecar": {
"globals": {
"console.error": true
},
"packages": {
"react": true,
"react-focus-lock>use-sidecar>detect-node-es": true,
"wait-on>rxjs>tslib": true
}
},
"react-idle-timer": {
"globals": {
"clearTimeout": true,
@ -4200,7 +4217,6 @@
},
"readable-stream": {
"packages": {
"@storybook/api>util-deprecate": true,
"browserify>browser-resolve": true,
"browserify>events": true,
"browserify>process": true,
@ -4210,7 +4226,8 @@
"readable-stream>isarray": true,
"readable-stream>process-nextick-args": true,
"readable-stream>safe-buffer": true,
"readable-stream>string_decoder": true
"readable-stream>string_decoder": true,
"readable-stream>util-deprecate": true
}
},
"readable-stream>core-util-is": {
@ -4233,6 +4250,13 @@
"readable-stream>safe-buffer": true
}
},
"readable-stream>util-deprecate": {
"globals": {
"console.trace": true,
"console.warn": true,
"localStorage": true
}
},
"redux": {
"globals": {
"console": true
@ -4247,6 +4271,7 @@
},
"packages": {
"browserify>process": true,
"browserify>util": true,
"semver>lru-cache": true
}
},
@ -4266,6 +4291,12 @@
"string.prototype.matchall>get-intrinsic": true
}
},
"string.prototype.matchall>es-abstract>is-regex": {
"packages": {
"koa>is-generator-function>has-tostringtag": true,
"string.prototype.matchall>call-bind": true
}
},
"string.prototype.matchall>get-intrinsic": {
"globals": {
"AggregateError": true,
@ -4275,6 +4306,7 @@
"packages": {
"browserify>has": true,
"browserify>has>function-bind": true,
"string.prototype.matchall>es-abstract>has-proto": true,
"string.prototype.matchall>has-symbols": true
}
},

View File

@ -5,6 +5,11 @@
"regeneratorRuntime": "write"
}
},
"@babel/runtime>regenerator-runtime": {
"globals": {
"regeneratorRuntime": "write"
}
},
"@download/blockies": {
"globals": {
"document.createElement": true
@ -868,6 +873,20 @@
"immer": true
}
},
"@metamask/browser-passworder": {
"globals": {
"btoa": true,
"crypto.getRandomValues": true,
"crypto.subtle.decrypt": true,
"crypto.subtle.deriveKey": true,
"crypto.subtle.encrypt": true,
"crypto.subtle.exportKey": true,
"crypto.subtle.importKey": true
},
"packages": {
"browserify>buffer": true
}
},
"@metamask/controller-utils": {
"globals": {
"URL": true,
@ -1069,11 +1088,11 @@
},
"@metamask/eth-keyring-controller": {
"packages": {
"@metamask/browser-passworder": true,
"@metamask/eth-keyring-controller>@metamask/eth-hd-keyring": true,
"@metamask/eth-keyring-controller>@metamask/eth-simple-keyring": true,
"@metamask/eth-keyring-controller>obs-store": true,
"@metamask/eth-trezor-keyring>@metamask/eth-sig-util": true,
"@metamask/rpc-methods>@metamask/browser-passworder": true,
"browserify>events": true
}
},
@ -1199,8 +1218,8 @@
"@metamask/eth-token-tracker>deep-equal>is-arguments": true,
"@metamask/eth-token-tracker>deep-equal>is-date-object": true,
"@ngraveio/bc-ur>assert>object-is": true,
"@storybook/api>telejson>is-regex": true,
"globalthis>define-properties>object-keys": true,
"string.prototype.matchall>es-abstract>is-regex": true,
"string.prototype.matchall>regexp.prototype.flags": true
}
},
@ -1683,25 +1702,12 @@
"browser": true,
"chrome": true,
"location.origin": true,
"onmessage": "write",
"postMessage": true,
"removeEventListener": true
},
"packages": {
"@metamask/post-message-stream>@metamask/utils": true,
"@metamask/post-message-stream>readable-stream": true
}
},
"@metamask/post-message-stream>@metamask/utils": {
"globals": {
"TextDecoder": true,
"TextEncoder": true
},
"packages": {
"browserify>buffer": true,
"nock>debug": true,
"semver": true,
"superstruct": true
"@metamask/post-message-stream>readable-stream": true,
"@metamask/utils": true
}
},
"@metamask/post-message-stream>readable-stream": {
@ -1709,14 +1715,14 @@
"@metamask/post-message-stream>readable-stream>process-nextick-args": true,
"@metamask/post-message-stream>readable-stream>safe-buffer": true,
"@metamask/post-message-stream>readable-stream>string_decoder": true,
"@storybook/api>util-deprecate": true,
"browserify>browser-resolve": true,
"browserify>events": true,
"browserify>process": true,
"browserify>timers-browserify": true,
"pumpify>inherits": true,
"readable-stream>core-util-is": true,
"readable-stream>isarray": true
"readable-stream>isarray": true,
"readable-stream>util-deprecate": true
}
},
"@metamask/post-message-stream>readable-stream>process-nextick-args": {
@ -1753,53 +1759,52 @@
"eth-rpc-errors": true
}
},
"@metamask/rpc-methods": {
"packages": {
"@metamask/key-tree": true,
"@metamask/key-tree>@noble/hashes": true,
"@metamask/permission-controller": true,
"@metamask/rpc-methods>@metamask/browser-passworder": true,
"@metamask/rpc-methods>nanoid": true,
"@metamask/snaps-ui": true,
"@metamask/snaps-utils": true,
"@metamask/utils": true,
"eth-rpc-errors": true,
"superstruct": true
}
},
"@metamask/rpc-methods-flask": {
"packages": {
"@metamask/key-tree": true,
"@metamask/key-tree>@noble/hashes": true,
"@metamask/permission-controller": true,
"@metamask/rpc-methods-flask>@metamask/snaps-ui": true,
"@metamask/rpc-methods-flask>@metamask/snaps-utils": true,
"@metamask/rpc-methods-flask>nanoid": true,
"@metamask/rpc-methods>@metamask/browser-passworder": true,
"@metamask/snaps-ui": true,
"@metamask/snaps-utils": true,
"@metamask/utils": true,
"eth-rpc-errors": true,
"superstruct": true
}
},
"@metamask/rpc-methods-flask>@metamask/snaps-ui": {
"packages": {
"@metamask/utils": true,
"superstruct": true
}
},
"@metamask/rpc-methods-flask>@metamask/snaps-utils": {
"globals": {
"TextDecoder": true,
"URL": true,
"console.error": true,
"console.log": true,
"console.warn": true,
"document.body.appendChild": true,
"document.createElement": true
},
"packages": {
"@metamask/key-tree>@noble/hashes": true,
"@metamask/key-tree>@scure/base": true,
"@metamask/snaps-utils>cron-parser": true,
"@metamask/snaps-utils>fast-json-stable-stringify": true,
"@metamask/snaps-utils>rfdc": true,
"@metamask/snaps-utils>validate-npm-package-name": true,
"@metamask/utils": true,
"semver": true,
"superstruct": true
}
},
"@metamask/rpc-methods-flask>nanoid": {
"globals": {
"crypto.getRandomValues": true
}
},
"@metamask/rpc-methods>@metamask/browser-passworder": {
"globals": {
"btoa": true,
"crypto.getRandomValues": true,
"crypto.subtle.decrypt": true,
"crypto.subtle.deriveKey": true,
"crypto.subtle.encrypt": true,
"crypto.subtle.exportKey": true,
"crypto.subtle.importKey": true
},
"packages": {
"browserify>buffer": true
}
},
"@metamask/rpc-methods>nanoid": {
"globals": {
"crypto.getRandomValues": true
@ -1829,25 +1834,13 @@
"packages": {
"@metamask/base-controller": true,
"@metamask/controller-utils": true,
"@metamask/signature-controller>@metamask/message-manager": true,
"@metamask/message-manager": true,
"browserify>buffer": true,
"browserify>events": true,
"eth-rpc-errors": true,
"ethereumjs-util": true
}
},
"@metamask/signature-controller>@metamask/message-manager": {
"packages": {
"@metamask/base-controller": true,
"@metamask/controller-utils": true,
"@metamask/message-manager>jsonschema": true,
"browserify>buffer": true,
"browserify>events": true,
"eth-sig-util": true,
"ethereumjs-util": true,
"uuid": true
}
},
"@metamask/smart-transactions-controller": {
"globals": {
"URLSearchParams": true,
@ -1934,16 +1927,15 @@
"@metamask/permission-controller": true,
"@metamask/post-message-stream": true,
"@metamask/providers>@metamask/object-multiplex": true,
"@metamask/rpc-methods": true,
"@metamask/snaps-controllers-flask>@metamask/rpc-methods": true,
"@metamask/snaps-controllers-flask>@metamask/snaps-utils": true,
"@metamask/snaps-controllers-flask>concat-stream": true,
"@metamask/snaps-controllers-flask>nanoid": true,
"@metamask/snaps-controllers>@xstate/fsm": true,
"@metamask/snaps-controllers>gunzip-maybe": true,
"@metamask/snaps-controllers>readable-web-to-node-stream": true,
"@metamask/snaps-controllers>tar-stream": true,
"@metamask/snaps-utils": true,
"@metamask/snaps-utils>@metamask/snaps-registry": true,
"@metamask/subject-metadata-controller": true,
"@metamask/utils": true,
"eth-rpc-errors": true,
"json-rpc-engine": true,
@ -1951,6 +1943,47 @@
"pump": true
}
},
"@metamask/snaps-controllers-flask>@metamask/rpc-methods": {
"packages": {
"@metamask/key-tree": true,
"@metamask/key-tree>@noble/hashes": true,
"@metamask/permission-controller": true,
"@metamask/snaps-controllers-flask>@metamask/snaps-utils": true,
"@metamask/snaps-controllers-flask>@metamask/snaps-utils>@metamask/snaps-ui": true,
"@metamask/snaps-controllers-flask>nanoid": true,
"@metamask/utils": true,
"eth-rpc-errors": true,
"superstruct": true
}
},
"@metamask/snaps-controllers-flask>@metamask/snaps-utils": {
"globals": {
"TextDecoder": true,
"URL": true,
"console.error": true,
"console.log": true,
"console.warn": true,
"document.body.appendChild": true,
"document.createElement": true
},
"packages": {
"@metamask/key-tree>@noble/hashes": true,
"@metamask/key-tree>@scure/base": true,
"@metamask/snaps-utils>cron-parser": true,
"@metamask/snaps-utils>fast-json-stable-stringify": true,
"@metamask/snaps-utils>rfdc": true,
"@metamask/snaps-utils>validate-npm-package-name": true,
"@metamask/utils": true,
"semver": true,
"superstruct": true
}
},
"@metamask/snaps-controllers-flask>@metamask/snaps-utils>@metamask/snaps-ui": {
"packages": {
"@metamask/utils": true,
"superstruct": true
}
},
"@metamask/snaps-controllers-flask>concat-stream": {
"packages": {
"@metamask/snaps-controllers-flask>concat-stream>readable-stream": true,
@ -1960,13 +1993,13 @@
},
"@metamask/snaps-controllers-flask>concat-stream>readable-stream": {
"packages": {
"@storybook/api>util-deprecate": true,
"browserify>browser-resolve": true,
"browserify>buffer": true,
"browserify>events": true,
"browserify>process": true,
"browserify>string_decoder": true,
"pumpify>inherits": true
"pumpify>inherits": true,
"readable-stream>util-deprecate": true
}
},
"@metamask/snaps-controllers-flask>nanoid": {
@ -2064,13 +2097,13 @@
},
"@metamask/snaps-controllers>readable-web-to-node-stream>readable-stream": {
"packages": {
"@storybook/api>util-deprecate": true,
"browserify>browser-resolve": true,
"browserify>buffer": true,
"browserify>events": true,
"browserify>process": true,
"browserify>string_decoder": true,
"pumpify>inherits": true
"pumpify>inherits": true,
"readable-stream>util-deprecate": true
}
},
"@metamask/snaps-controllers>tar-stream": {
@ -2093,19 +2126,13 @@
},
"@metamask/snaps-controllers>tar-stream>readable-stream": {
"packages": {
"@storybook/api>util-deprecate": true,
"browserify>browser-resolve": true,
"browserify>buffer": true,
"browserify>events": true,
"browserify>process": true,
"browserify>string_decoder": true,
"pumpify>inherits": true
}
},
"@metamask/snaps-ui": {
"packages": {
"@metamask/utils": true,
"superstruct": true
"pumpify>inherits": true,
"readable-stream>util-deprecate": true
}
},
"@metamask/snaps-ui-flask": {
@ -2114,28 +2141,6 @@
"superstruct": true
}
},
"@metamask/snaps-utils": {
"globals": {
"TextDecoder": true,
"URL": true,
"console.error": true,
"console.log": true,
"console.warn": true,
"document.body.appendChild": true,
"document.createElement": true
},
"packages": {
"@metamask/key-tree>@noble/hashes": true,
"@metamask/key-tree>@scure/base": true,
"@metamask/snaps-utils>cron-parser": true,
"@metamask/snaps-utils>fast-json-stable-stringify": true,
"@metamask/snaps-utils>rfdc": true,
"@metamask/snaps-utils>validate-npm-package-name": true,
"@metamask/utils": true,
"semver": true,
"superstruct": true
}
},
"@metamask/snaps-utils-flask": {
"globals": {
"TextDecoder": true,
@ -2398,24 +2403,6 @@
"define": true
}
},
"@storybook/api>regenerator-runtime": {
"globals": {
"regeneratorRuntime": "write"
}
},
"@storybook/api>telejson>is-regex": {
"packages": {
"koa>is-generator-function>has-tostringtag": true,
"string.prototype.matchall>call-bind": true
}
},
"@storybook/api>util-deprecate": {
"globals": {
"console.trace": true,
"console.warn": true,
"localStorage": true
}
},
"@truffle/codec": {
"packages": {
"@truffle/codec>@truffle/abi-utils": true,
@ -2512,16 +2499,10 @@
},
"@truffle/codec>@truffle/abi-utils>change-case>pascal-case": {
"packages": {
"@truffle/codec>@truffle/abi-utils>change-case>pascal-case>camel-case": true,
"@truffle/codec>@truffle/abi-utils>change-case>camel-case": true,
"@truffle/codec>@truffle/abi-utils>change-case>upper-case-first": true
}
},
"@truffle/codec>@truffle/abi-utils>change-case>pascal-case>camel-case": {
"packages": {
"@truffle/codec>@truffle/abi-utils>change-case>no-case": true,
"@truffle/codec>@truffle/abi-utils>change-case>upper-case": true
}
},
"@truffle/codec>@truffle/abi-utils>change-case>path-case": {
"packages": {
"@truffle/codec>@truffle/abi-utils>change-case>no-case": true
@ -2628,13 +2609,8 @@
"console.error": true
},
"packages": {
"@truffle/codec>semver>lru-cache": true,
"browserify>process": true
}
},
"@truffle/codec>semver>lru-cache": {
"packages": {
"semver>lru-cache>yallist": true
"browserify>process": true,
"semver>lru-cache": true
}
},
"@truffle/codec>web3-utils": {
@ -2692,9 +2668,9 @@
"@truffle/codec": true,
"@truffle/codec>@truffle/abi-utils": true,
"@truffle/codec>@truffle/compile-common": true,
"@truffle/codec>big.js": true,
"@truffle/codec>web3-utils": true,
"@truffle/decoder>@truffle/encoder>@ensdomains/ensjs": true,
"@truffle/decoder>@truffle/encoder>big.js": true,
"@truffle/decoder>@truffle/encoder>bignumber.js": true,
"lodash": true,
"nock>debug": true
@ -2871,11 +2847,6 @@
"browserify>process": true
}
},
"@truffle/decoder>@truffle/encoder>big.js": {
"globals": {
"define": true
}
},
"@truffle/decoder>@truffle/encoder>bignumber.js": {
"globals": {
"crypto": true,
@ -2905,7 +2876,7 @@
},
"@truffle/decoder>@truffle/source-map-utils>node-interval-tree": {
"packages": {
"@storybook/addon-a11y>react-sizeme>shallowequal": true
"@truffle/decoder>@truffle/source-map-utils>node-interval-tree>shallowequal": true
}
},
"@truffle/decoder>bn.js": {
@ -3738,13 +3709,13 @@
},
"ethereumjs-util>create-hash>md5.js>hash-base>readable-stream": {
"packages": {
"@storybook/api>util-deprecate": true,
"browserify>browser-resolve": true,
"browserify>buffer": true,
"browserify>events": true,
"browserify>process": true,
"browserify>string_decoder": true,
"pumpify>inherits": true
"pumpify>inherits": true,
"readable-stream>util-deprecate": true
}
},
"ethereumjs-util>create-hash>ripemd160": {
@ -3791,13 +3762,13 @@
},
"ethereumjs-util>ethereum-cryptography>keccak>readable-stream": {
"packages": {
"@storybook/api>util-deprecate": true,
"browserify>browser-resolve": true,
"browserify>buffer": true,
"browserify>events": true,
"browserify>process": true,
"browserify>string_decoder": true,
"pumpify>inherits": true
"pumpify>inherits": true,
"readable-stream>util-deprecate": true
}
},
"ethereumjs-util>ethereum-cryptography>scrypt-js": {
@ -3972,7 +3943,7 @@
"ethjs-query>babel-runtime": {
"packages": {
"@babel/runtime": true,
"@storybook/api>regenerator-runtime": true,
"@babel/runtime>regenerator-runtime": true,
"ethjs-query>babel-runtime>core-js": true
}
},
@ -4195,13 +4166,13 @@
},
"madge>ora>bl>readable-stream": {
"packages": {
"@storybook/api>util-deprecate": true,
"browserify>browser-resolve": true,
"browserify>buffer": true,
"browserify>events": true,
"browserify>process": true,
"browserify>string_decoder": true,
"pumpify>inherits": true
"pumpify>inherits": true,
"readable-stream>util-deprecate": true
}
},
"nanoid": {
@ -4374,6 +4345,64 @@
"setTimeout": true
}
},
"react-focus-lock": {
"globals": {
"addEventListener": true,
"console.error": true,
"console.warn": true,
"document": true,
"removeEventListener": true,
"setTimeout": true
},
"packages": {
"@babel/runtime": true,
"prop-types": true,
"react": true,
"react-focus-lock>focus-lock": true,
"react-focus-lock>react-clientside-effect": true,
"react-focus-lock>use-callback-ref": true,
"react-focus-lock>use-sidecar": true
}
},
"react-focus-lock>focus-lock": {
"globals": {
"HTMLIFrameElement": true,
"Node.DOCUMENT_FRAGMENT_NODE": true,
"Node.DOCUMENT_NODE": true,
"Node.DOCUMENT_POSITION_CONTAINED_BY": true,
"Node.DOCUMENT_POSITION_CONTAINS": true,
"Node.ELEMENT_NODE": true,
"console.error": true,
"console.warn": true,
"document": true,
"getComputedStyle": true,
"setTimeout": true
},
"packages": {
"wait-on>rxjs>tslib": true
}
},
"react-focus-lock>react-clientside-effect": {
"packages": {
"@babel/runtime": true,
"react": true
}
},
"react-focus-lock>use-callback-ref": {
"packages": {
"react": true
}
},
"react-focus-lock>use-sidecar": {
"globals": {
"console.error": true
},
"packages": {
"react": true,
"react-focus-lock>use-sidecar>detect-node-es": true,
"wait-on>rxjs>tslib": true
}
},
"react-idle-timer": {
"globals": {
"clearTimeout": true,
@ -4450,7 +4479,7 @@
"packages": {
"react-markdown>remark-parse>mdast-util-from-markdown>mdast-util-to-string": true,
"react-markdown>remark-parse>mdast-util-from-markdown>micromark": true,
"react-markdown>vfile>unist-util-stringify-position": true,
"react-markdown>remark-parse>mdast-util-from-markdown>unist-util-stringify-position": true,
"react-syntax-highlighter>refractor>parse-entities": true
}
},
@ -4766,7 +4795,6 @@
},
"readable-stream": {
"packages": {
"@storybook/api>util-deprecate": true,
"browserify>browser-resolve": true,
"browserify>events": true,
"browserify>process": true,
@ -4776,7 +4804,8 @@
"readable-stream>isarray": true,
"readable-stream>process-nextick-args": true,
"readable-stream>safe-buffer": true,
"readable-stream>string_decoder": true
"readable-stream>string_decoder": true,
"readable-stream>util-deprecate": true
}
},
"readable-stream>core-util-is": {
@ -4799,6 +4828,13 @@
"readable-stream>safe-buffer": true
}
},
"readable-stream>util-deprecate": {
"globals": {
"console.trace": true,
"console.warn": true,
"localStorage": true
}
},
"redux": {
"globals": {
"console": true
@ -4813,6 +4849,7 @@
},
"packages": {
"browserify>process": true,
"browserify>util": true,
"semver>lru-cache": true
}
},
@ -4832,6 +4869,12 @@
"string.prototype.matchall>get-intrinsic": true
}
},
"string.prototype.matchall>es-abstract>is-regex": {
"packages": {
"koa>is-generator-function>has-tostringtag": true,
"string.prototype.matchall>call-bind": true
}
},
"string.prototype.matchall>get-intrinsic": {
"globals": {
"AggregateError": true,
@ -4841,6 +4884,7 @@
"packages": {
"browserify>has": true,
"browserify>has>function-bind": true,
"string.prototype.matchall>es-abstract>has-proto": true,
"string.prototype.matchall>has-symbols": true
}
},

View File

@ -5,6 +5,11 @@
"regeneratorRuntime": "write"
}
},
"@babel/runtime>regenerator-runtime": {
"globals": {
"regeneratorRuntime": "write"
}
},
"@download/blockies": {
"globals": {
"document.createElement": true
@ -868,6 +873,20 @@
"immer": true
}
},
"@metamask/browser-passworder": {
"globals": {
"btoa": true,
"crypto.getRandomValues": true,
"crypto.subtle.decrypt": true,
"crypto.subtle.deriveKey": true,
"crypto.subtle.encrypt": true,
"crypto.subtle.exportKey": true,
"crypto.subtle.importKey": true
},
"packages": {
"browserify>buffer": true
}
},
"@metamask/controller-utils": {
"globals": {
"URL": true,
@ -1069,11 +1088,11 @@
},
"@metamask/eth-keyring-controller": {
"packages": {
"@metamask/browser-passworder": true,
"@metamask/eth-keyring-controller>@metamask/eth-hd-keyring": true,
"@metamask/eth-keyring-controller>@metamask/eth-simple-keyring": true,
"@metamask/eth-keyring-controller>obs-store": true,
"@metamask/eth-trezor-keyring>@metamask/eth-sig-util": true,
"@metamask/rpc-methods>@metamask/browser-passworder": true,
"browserify>events": true
}
},
@ -1199,8 +1218,8 @@
"@metamask/eth-token-tracker>deep-equal>is-arguments": true,
"@metamask/eth-token-tracker>deep-equal>is-date-object": true,
"@ngraveio/bc-ur>assert>object-is": true,
"@storybook/api>telejson>is-regex": true,
"globalthis>define-properties>object-keys": true,
"string.prototype.matchall>es-abstract>is-regex": true,
"string.prototype.matchall>regexp.prototype.flags": true
}
},
@ -1683,25 +1702,12 @@
"browser": true,
"chrome": true,
"location.origin": true,
"onmessage": "write",
"postMessage": true,
"removeEventListener": true
},
"packages": {
"@metamask/post-message-stream>@metamask/utils": true,
"@metamask/post-message-stream>readable-stream": true
}
},
"@metamask/post-message-stream>@metamask/utils": {
"globals": {
"TextDecoder": true,
"TextEncoder": true
},
"packages": {
"browserify>buffer": true,
"nock>debug": true,
"semver": true,
"superstruct": true
"@metamask/post-message-stream>readable-stream": true,
"@metamask/utils": true
}
},
"@metamask/post-message-stream>readable-stream": {
@ -1709,14 +1715,14 @@
"@metamask/post-message-stream>readable-stream>process-nextick-args": true,
"@metamask/post-message-stream>readable-stream>safe-buffer": true,
"@metamask/post-message-stream>readable-stream>string_decoder": true,
"@storybook/api>util-deprecate": true,
"browserify>browser-resolve": true,
"browserify>events": true,
"browserify>process": true,
"browserify>timers-browserify": true,
"pumpify>inherits": true,
"readable-stream>core-util-is": true,
"readable-stream>isarray": true
"readable-stream>isarray": true,
"readable-stream>util-deprecate": true
}
},
"@metamask/post-message-stream>readable-stream>process-nextick-args": {
@ -1753,53 +1759,52 @@
"eth-rpc-errors": true
}
},
"@metamask/rpc-methods": {
"packages": {
"@metamask/key-tree": true,
"@metamask/key-tree>@noble/hashes": true,
"@metamask/permission-controller": true,
"@metamask/rpc-methods>@metamask/browser-passworder": true,
"@metamask/rpc-methods>nanoid": true,
"@metamask/snaps-ui": true,
"@metamask/snaps-utils": true,
"@metamask/utils": true,
"eth-rpc-errors": true,
"superstruct": true
}
},
"@metamask/rpc-methods-flask": {
"packages": {
"@metamask/key-tree": true,
"@metamask/key-tree>@noble/hashes": true,
"@metamask/permission-controller": true,
"@metamask/rpc-methods-flask>@metamask/snaps-ui": true,
"@metamask/rpc-methods-flask>@metamask/snaps-utils": true,
"@metamask/rpc-methods-flask>nanoid": true,
"@metamask/rpc-methods>@metamask/browser-passworder": true,
"@metamask/snaps-ui": true,
"@metamask/snaps-utils": true,
"@metamask/utils": true,
"eth-rpc-errors": true,
"superstruct": true
}
},
"@metamask/rpc-methods-flask>@metamask/snaps-ui": {
"packages": {
"@metamask/utils": true,
"superstruct": true
}
},
"@metamask/rpc-methods-flask>@metamask/snaps-utils": {
"globals": {
"TextDecoder": true,
"URL": true,
"console.error": true,
"console.log": true,
"console.warn": true,
"document.body.appendChild": true,
"document.createElement": true
},
"packages": {
"@metamask/key-tree>@noble/hashes": true,
"@metamask/key-tree>@scure/base": true,
"@metamask/snaps-utils>cron-parser": true,
"@metamask/snaps-utils>fast-json-stable-stringify": true,
"@metamask/snaps-utils>rfdc": true,
"@metamask/snaps-utils>validate-npm-package-name": true,
"@metamask/utils": true,
"semver": true,
"superstruct": true
}
},
"@metamask/rpc-methods-flask>nanoid": {
"globals": {
"crypto.getRandomValues": true
}
},
"@metamask/rpc-methods>@metamask/browser-passworder": {
"globals": {
"btoa": true,
"crypto.getRandomValues": true,
"crypto.subtle.decrypt": true,
"crypto.subtle.deriveKey": true,
"crypto.subtle.encrypt": true,
"crypto.subtle.exportKey": true,
"crypto.subtle.importKey": true
},
"packages": {
"browserify>buffer": true
}
},
"@metamask/rpc-methods>nanoid": {
"globals": {
"crypto.getRandomValues": true
@ -1829,25 +1834,13 @@
"packages": {
"@metamask/base-controller": true,
"@metamask/controller-utils": true,
"@metamask/signature-controller>@metamask/message-manager": true,
"@metamask/message-manager": true,
"browserify>buffer": true,
"browserify>events": true,
"eth-rpc-errors": true,
"ethereumjs-util": true
}
},
"@metamask/signature-controller>@metamask/message-manager": {
"packages": {
"@metamask/base-controller": true,
"@metamask/controller-utils": true,
"@metamask/message-manager>jsonschema": true,
"browserify>buffer": true,
"browserify>events": true,
"eth-sig-util": true,
"ethereumjs-util": true,
"uuid": true
}
},
"@metamask/smart-transactions-controller": {
"globals": {
"URLSearchParams": true,
@ -1934,16 +1927,15 @@
"@metamask/permission-controller": true,
"@metamask/post-message-stream": true,
"@metamask/providers>@metamask/object-multiplex": true,
"@metamask/rpc-methods": true,
"@metamask/snaps-controllers-flask>@metamask/rpc-methods": true,
"@metamask/snaps-controllers-flask>@metamask/snaps-utils": true,
"@metamask/snaps-controllers-flask>concat-stream": true,
"@metamask/snaps-controllers-flask>nanoid": true,
"@metamask/snaps-controllers>@xstate/fsm": true,
"@metamask/snaps-controllers>gunzip-maybe": true,
"@metamask/snaps-controllers>readable-web-to-node-stream": true,
"@metamask/snaps-controllers>tar-stream": true,
"@metamask/snaps-utils": true,
"@metamask/snaps-utils>@metamask/snaps-registry": true,
"@metamask/subject-metadata-controller": true,
"@metamask/utils": true,
"eth-rpc-errors": true,
"json-rpc-engine": true,
@ -1951,6 +1943,47 @@
"pump": true
}
},
"@metamask/snaps-controllers-flask>@metamask/rpc-methods": {
"packages": {
"@metamask/key-tree": true,
"@metamask/key-tree>@noble/hashes": true,
"@metamask/permission-controller": true,
"@metamask/snaps-controllers-flask>@metamask/snaps-utils": true,
"@metamask/snaps-controllers-flask>@metamask/snaps-utils>@metamask/snaps-ui": true,
"@metamask/snaps-controllers-flask>nanoid": true,
"@metamask/utils": true,
"eth-rpc-errors": true,
"superstruct": true
}
},
"@metamask/snaps-controllers-flask>@metamask/snaps-utils": {
"globals": {
"TextDecoder": true,
"URL": true,
"console.error": true,
"console.log": true,
"console.warn": true,
"document.body.appendChild": true,
"document.createElement": true
},
"packages": {
"@metamask/key-tree>@noble/hashes": true,
"@metamask/key-tree>@scure/base": true,
"@metamask/snaps-utils>cron-parser": true,
"@metamask/snaps-utils>fast-json-stable-stringify": true,
"@metamask/snaps-utils>rfdc": true,
"@metamask/snaps-utils>validate-npm-package-name": true,
"@metamask/utils": true,
"semver": true,
"superstruct": true
}
},
"@metamask/snaps-controllers-flask>@metamask/snaps-utils>@metamask/snaps-ui": {
"packages": {
"@metamask/utils": true,
"superstruct": true
}
},
"@metamask/snaps-controllers-flask>concat-stream": {
"packages": {
"@metamask/snaps-controllers-flask>concat-stream>readable-stream": true,
@ -1960,13 +1993,13 @@
},
"@metamask/snaps-controllers-flask>concat-stream>readable-stream": {
"packages": {
"@storybook/api>util-deprecate": true,
"browserify>browser-resolve": true,
"browserify>buffer": true,
"browserify>events": true,
"browserify>process": true,
"browserify>string_decoder": true,
"pumpify>inherits": true
"pumpify>inherits": true,
"readable-stream>util-deprecate": true
}
},
"@metamask/snaps-controllers-flask>nanoid": {
@ -2064,13 +2097,13 @@
},
"@metamask/snaps-controllers>readable-web-to-node-stream>readable-stream": {
"packages": {
"@storybook/api>util-deprecate": true,
"browserify>browser-resolve": true,
"browserify>buffer": true,
"browserify>events": true,
"browserify>process": true,
"browserify>string_decoder": true,
"pumpify>inherits": true
"pumpify>inherits": true,
"readable-stream>util-deprecate": true
}
},
"@metamask/snaps-controllers>tar-stream": {
@ -2093,19 +2126,13 @@
},
"@metamask/snaps-controllers>tar-stream>readable-stream": {
"packages": {
"@storybook/api>util-deprecate": true,
"browserify>browser-resolve": true,
"browserify>buffer": true,
"browserify>events": true,
"browserify>process": true,
"browserify>string_decoder": true,
"pumpify>inherits": true
}
},
"@metamask/snaps-ui": {
"packages": {
"@metamask/utils": true,
"superstruct": true
"pumpify>inherits": true,
"readable-stream>util-deprecate": true
}
},
"@metamask/snaps-ui-flask": {
@ -2114,28 +2141,6 @@
"superstruct": true
}
},
"@metamask/snaps-utils": {
"globals": {
"TextDecoder": true,
"URL": true,
"console.error": true,
"console.log": true,
"console.warn": true,
"document.body.appendChild": true,
"document.createElement": true
},
"packages": {
"@metamask/key-tree>@noble/hashes": true,
"@metamask/key-tree>@scure/base": true,
"@metamask/snaps-utils>cron-parser": true,
"@metamask/snaps-utils>fast-json-stable-stringify": true,
"@metamask/snaps-utils>rfdc": true,
"@metamask/snaps-utils>validate-npm-package-name": true,
"@metamask/utils": true,
"semver": true,
"superstruct": true
}
},
"@metamask/snaps-utils-flask": {
"globals": {
"TextDecoder": true,
@ -2398,24 +2403,6 @@
"define": true
}
},
"@storybook/api>regenerator-runtime": {
"globals": {
"regeneratorRuntime": "write"
}
},
"@storybook/api>telejson>is-regex": {
"packages": {
"koa>is-generator-function>has-tostringtag": true,
"string.prototype.matchall>call-bind": true
}
},
"@storybook/api>util-deprecate": {
"globals": {
"console.trace": true,
"console.warn": true,
"localStorage": true
}
},
"@truffle/codec": {
"packages": {
"@truffle/codec>@truffle/abi-utils": true,
@ -2512,16 +2499,10 @@
},
"@truffle/codec>@truffle/abi-utils>change-case>pascal-case": {
"packages": {
"@truffle/codec>@truffle/abi-utils>change-case>pascal-case>camel-case": true,
"@truffle/codec>@truffle/abi-utils>change-case>camel-case": true,
"@truffle/codec>@truffle/abi-utils>change-case>upper-case-first": true
}
},
"@truffle/codec>@truffle/abi-utils>change-case>pascal-case>camel-case": {
"packages": {
"@truffle/codec>@truffle/abi-utils>change-case>no-case": true,
"@truffle/codec>@truffle/abi-utils>change-case>upper-case": true
}
},
"@truffle/codec>@truffle/abi-utils>change-case>path-case": {
"packages": {
"@truffle/codec>@truffle/abi-utils>change-case>no-case": true
@ -2628,13 +2609,8 @@
"console.error": true
},
"packages": {
"@truffle/codec>semver>lru-cache": true,
"browserify>process": true
}
},
"@truffle/codec>semver>lru-cache": {
"packages": {
"semver>lru-cache>yallist": true
"browserify>process": true,
"semver>lru-cache": true
}
},
"@truffle/codec>web3-utils": {
@ -2692,9 +2668,9 @@
"@truffle/codec": true,
"@truffle/codec>@truffle/abi-utils": true,
"@truffle/codec>@truffle/compile-common": true,
"@truffle/codec>big.js": true,
"@truffle/codec>web3-utils": true,
"@truffle/decoder>@truffle/encoder>@ensdomains/ensjs": true,
"@truffle/decoder>@truffle/encoder>big.js": true,
"@truffle/decoder>@truffle/encoder>bignumber.js": true,
"lodash": true,
"nock>debug": true
@ -2871,11 +2847,6 @@
"browserify>process": true
}
},
"@truffle/decoder>@truffle/encoder>big.js": {
"globals": {
"define": true
}
},
"@truffle/decoder>@truffle/encoder>bignumber.js": {
"globals": {
"crypto": true,
@ -2905,7 +2876,7 @@
},
"@truffle/decoder>@truffle/source-map-utils>node-interval-tree": {
"packages": {
"@storybook/addon-a11y>react-sizeme>shallowequal": true
"@truffle/decoder>@truffle/source-map-utils>node-interval-tree>shallowequal": true
}
},
"@truffle/decoder>bn.js": {
@ -3738,13 +3709,13 @@
},
"ethereumjs-util>create-hash>md5.js>hash-base>readable-stream": {
"packages": {
"@storybook/api>util-deprecate": true,
"browserify>browser-resolve": true,
"browserify>buffer": true,
"browserify>events": true,
"browserify>process": true,
"browserify>string_decoder": true,
"pumpify>inherits": true
"pumpify>inherits": true,
"readable-stream>util-deprecate": true
}
},
"ethereumjs-util>create-hash>ripemd160": {
@ -3791,13 +3762,13 @@
},
"ethereumjs-util>ethereum-cryptography>keccak>readable-stream": {
"packages": {
"@storybook/api>util-deprecate": true,
"browserify>browser-resolve": true,
"browserify>buffer": true,
"browserify>events": true,
"browserify>process": true,
"browserify>string_decoder": true,
"pumpify>inherits": true
"pumpify>inherits": true,
"readable-stream>util-deprecate": true
}
},
"ethereumjs-util>ethereum-cryptography>scrypt-js": {
@ -3972,7 +3943,7 @@
"ethjs-query>babel-runtime": {
"packages": {
"@babel/runtime": true,
"@storybook/api>regenerator-runtime": true,
"@babel/runtime>regenerator-runtime": true,
"ethjs-query>babel-runtime>core-js": true
}
},
@ -4195,13 +4166,13 @@
},
"madge>ora>bl>readable-stream": {
"packages": {
"@storybook/api>util-deprecate": true,
"browserify>browser-resolve": true,
"browserify>buffer": true,
"browserify>events": true,
"browserify>process": true,
"browserify>string_decoder": true,
"pumpify>inherits": true
"pumpify>inherits": true,
"readable-stream>util-deprecate": true
}
},
"nanoid": {
@ -4374,6 +4345,64 @@
"setTimeout": true
}
},
"react-focus-lock": {
"globals": {
"addEventListener": true,
"console.error": true,
"console.warn": true,
"document": true,
"removeEventListener": true,
"setTimeout": true
},
"packages": {
"@babel/runtime": true,
"prop-types": true,
"react": true,
"react-focus-lock>focus-lock": true,
"react-focus-lock>react-clientside-effect": true,
"react-focus-lock>use-callback-ref": true,
"react-focus-lock>use-sidecar": true
}
},
"react-focus-lock>focus-lock": {
"globals": {
"HTMLIFrameElement": true,
"Node.DOCUMENT_FRAGMENT_NODE": true,
"Node.DOCUMENT_NODE": true,
"Node.DOCUMENT_POSITION_CONTAINED_BY": true,
"Node.DOCUMENT_POSITION_CONTAINS": true,
"Node.ELEMENT_NODE": true,
"console.error": true,
"console.warn": true,
"document": true,
"getComputedStyle": true,
"setTimeout": true
},
"packages": {
"wait-on>rxjs>tslib": true
}
},
"react-focus-lock>react-clientside-effect": {
"packages": {
"@babel/runtime": true,
"react": true
}
},
"react-focus-lock>use-callback-ref": {
"packages": {
"react": true
}
},
"react-focus-lock>use-sidecar": {
"globals": {
"console.error": true
},
"packages": {
"react": true,
"react-focus-lock>use-sidecar>detect-node-es": true,
"wait-on>rxjs>tslib": true
}
},
"react-idle-timer": {
"globals": {
"clearTimeout": true,
@ -4450,7 +4479,7 @@
"packages": {
"react-markdown>remark-parse>mdast-util-from-markdown>mdast-util-to-string": true,
"react-markdown>remark-parse>mdast-util-from-markdown>micromark": true,
"react-markdown>vfile>unist-util-stringify-position": true,
"react-markdown>remark-parse>mdast-util-from-markdown>unist-util-stringify-position": true,
"react-syntax-highlighter>refractor>parse-entities": true
}
},
@ -4766,7 +4795,6 @@
},
"readable-stream": {
"packages": {
"@storybook/api>util-deprecate": true,
"browserify>browser-resolve": true,
"browserify>events": true,
"browserify>process": true,
@ -4776,7 +4804,8 @@
"readable-stream>isarray": true,
"readable-stream>process-nextick-args": true,
"readable-stream>safe-buffer": true,
"readable-stream>string_decoder": true
"readable-stream>string_decoder": true,
"readable-stream>util-deprecate": true
}
},
"readable-stream>core-util-is": {
@ -4799,6 +4828,13 @@
"readable-stream>safe-buffer": true
}
},
"readable-stream>util-deprecate": {
"globals": {
"console.trace": true,
"console.warn": true,
"localStorage": true
}
},
"redux": {
"globals": {
"console": true
@ -4813,6 +4849,7 @@
},
"packages": {
"browserify>process": true,
"browserify>util": true,
"semver>lru-cache": true
}
},
@ -4832,6 +4869,12 @@
"string.prototype.matchall>get-intrinsic": true
}
},
"string.prototype.matchall>es-abstract>is-regex": {
"packages": {
"koa>is-generator-function>has-tostringtag": true,
"string.prototype.matchall>call-bind": true
}
},
"string.prototype.matchall>get-intrinsic": {
"globals": {
"AggregateError": true,
@ -4841,6 +4884,7 @@
"packages": {
"browserify>has": true,
"browserify>has>function-bind": true,
"string.prototype.matchall>es-abstract>has-proto": true,
"string.prototype.matchall>has-symbols": true
}
},

View File

@ -5,6 +5,11 @@
"regeneratorRuntime": "write"
}
},
"@babel/runtime>regenerator-runtime": {
"globals": {
"regeneratorRuntime": "write"
}
},
"@download/blockies": {
"globals": {
"document.createElement": true
@ -868,6 +873,20 @@
"immer": true
}
},
"@metamask/browser-passworder": {
"globals": {
"btoa": true,
"crypto.getRandomValues": true,
"crypto.subtle.decrypt": true,
"crypto.subtle.deriveKey": true,
"crypto.subtle.encrypt": true,
"crypto.subtle.exportKey": true,
"crypto.subtle.importKey": true
},
"packages": {
"browserify>buffer": true
}
},
"@metamask/controller-utils": {
"globals": {
"URL": true,
@ -998,11 +1017,11 @@
},
"@metamask/eth-keyring-controller": {
"packages": {
"@metamask/browser-passworder": true,
"@metamask/eth-keyring-controller>@metamask/eth-hd-keyring": true,
"@metamask/eth-keyring-controller>@metamask/eth-simple-keyring": true,
"@metamask/eth-keyring-controller>obs-store": true,
"@metamask/eth-trezor-keyring>@metamask/eth-sig-util": true,
"@metamask/rpc-methods>@metamask/browser-passworder": true,
"browserify>events": true
}
},
@ -1128,8 +1147,8 @@
"@metamask/eth-token-tracker>deep-equal>is-arguments": true,
"@metamask/eth-token-tracker>deep-equal>is-date-object": true,
"@ngraveio/bc-ur>assert>object-is": true,
"@storybook/api>telejson>is-regex": true,
"globalthis>define-properties>object-keys": true,
"string.prototype.matchall>es-abstract>is-regex": true,
"string.prototype.matchall>regexp.prototype.flags": true
}
},
@ -1610,20 +1629,6 @@
"crypto.getRandomValues": true
}
},
"@metamask/rpc-methods>@metamask/browser-passworder": {
"globals": {
"btoa": true,
"crypto.getRandomValues": true,
"crypto.subtle.decrypt": true,
"crypto.subtle.deriveKey": true,
"crypto.subtle.encrypt": true,
"crypto.subtle.exportKey": true,
"crypto.subtle.importKey": true
},
"packages": {
"browserify>buffer": true
}
},
"@metamask/rpc-methods>nanoid": {
"globals": {
"crypto.getRandomValues": true
@ -1653,25 +1658,13 @@
"packages": {
"@metamask/base-controller": true,
"@metamask/controller-utils": true,
"@metamask/signature-controller>@metamask/message-manager": true,
"@metamask/message-manager": true,
"browserify>buffer": true,
"browserify>events": true,
"eth-rpc-errors": true,
"ethereumjs-util": true
}
},
"@metamask/signature-controller>@metamask/message-manager": {
"packages": {
"@metamask/base-controller": true,
"@metamask/controller-utils": true,
"@metamask/message-manager>jsonschema": true,
"browserify>buffer": true,
"browserify>events": true,
"eth-sig-util": true,
"ethereumjs-util": true,
"uuid": true
}
},
"@metamask/smart-transactions-controller": {
"globals": {
"URLSearchParams": true,
@ -1964,24 +1957,6 @@
"define": true
}
},
"@storybook/api>regenerator-runtime": {
"globals": {
"regeneratorRuntime": "write"
}
},
"@storybook/api>telejson>is-regex": {
"packages": {
"koa>is-generator-function>has-tostringtag": true,
"string.prototype.matchall>call-bind": true
}
},
"@storybook/api>util-deprecate": {
"globals": {
"console.trace": true,
"console.warn": true,
"localStorage": true
}
},
"@truffle/codec": {
"packages": {
"@truffle/codec>@truffle/abi-utils": true,
@ -2078,16 +2053,10 @@
},
"@truffle/codec>@truffle/abi-utils>change-case>pascal-case": {
"packages": {
"@truffle/codec>@truffle/abi-utils>change-case>pascal-case>camel-case": true,
"@truffle/codec>@truffle/abi-utils>change-case>camel-case": true,
"@truffle/codec>@truffle/abi-utils>change-case>upper-case-first": true
}
},
"@truffle/codec>@truffle/abi-utils>change-case>pascal-case>camel-case": {
"packages": {
"@truffle/codec>@truffle/abi-utils>change-case>no-case": true,
"@truffle/codec>@truffle/abi-utils>change-case>upper-case": true
}
},
"@truffle/codec>@truffle/abi-utils>change-case>path-case": {
"packages": {
"@truffle/codec>@truffle/abi-utils>change-case>no-case": true
@ -2194,13 +2163,8 @@
"console.error": true
},
"packages": {
"@truffle/codec>semver>lru-cache": true,
"browserify>process": true
}
},
"@truffle/codec>semver>lru-cache": {
"packages": {
"semver>lru-cache>yallist": true
"browserify>process": true,
"semver>lru-cache": true
}
},
"@truffle/codec>web3-utils": {
@ -2258,9 +2222,9 @@
"@truffle/codec": true,
"@truffle/codec>@truffle/abi-utils": true,
"@truffle/codec>@truffle/compile-common": true,
"@truffle/codec>big.js": true,
"@truffle/codec>web3-utils": true,
"@truffle/decoder>@truffle/encoder>@ensdomains/ensjs": true,
"@truffle/decoder>@truffle/encoder>big.js": true,
"@truffle/decoder>@truffle/encoder>bignumber.js": true,
"lodash": true,
"nock>debug": true
@ -2437,11 +2401,6 @@
"browserify>process": true
}
},
"@truffle/decoder>@truffle/encoder>big.js": {
"globals": {
"define": true
}
},
"@truffle/decoder>@truffle/encoder>bignumber.js": {
"globals": {
"crypto": true,
@ -2471,7 +2430,7 @@
},
"@truffle/decoder>@truffle/source-map-utils>node-interval-tree": {
"packages": {
"@storybook/addon-a11y>react-sizeme>shallowequal": true
"@truffle/decoder>@truffle/source-map-utils>node-interval-tree>shallowequal": true
}
},
"@truffle/decoder>bn.js": {
@ -3304,13 +3263,13 @@
},
"ethereumjs-util>create-hash>md5.js>hash-base>readable-stream": {
"packages": {
"@storybook/api>util-deprecate": true,
"browserify>browser-resolve": true,
"browserify>buffer": true,
"browserify>events": true,
"browserify>process": true,
"browserify>string_decoder": true,
"pumpify>inherits": true
"pumpify>inherits": true,
"readable-stream>util-deprecate": true
}
},
"ethereumjs-util>create-hash>ripemd160": {
@ -3357,13 +3316,13 @@
},
"ethereumjs-util>ethereum-cryptography>keccak>readable-stream": {
"packages": {
"@storybook/api>util-deprecate": true,
"browserify>browser-resolve": true,
"browserify>buffer": true,
"browserify>events": true,
"browserify>process": true,
"browserify>string_decoder": true,
"pumpify>inherits": true
"pumpify>inherits": true,
"readable-stream>util-deprecate": true
}
},
"ethereumjs-util>ethereum-cryptography>scrypt-js": {
@ -3538,7 +3497,7 @@
"ethjs-query>babel-runtime": {
"packages": {
"@babel/runtime": true,
"@storybook/api>regenerator-runtime": true,
"@babel/runtime>regenerator-runtime": true,
"ethjs-query>babel-runtime>core-js": true
}
},
@ -3922,6 +3881,64 @@
"setTimeout": true
}
},
"react-focus-lock": {
"globals": {
"addEventListener": true,
"console.error": true,
"console.warn": true,
"document": true,
"removeEventListener": true,
"setTimeout": true
},
"packages": {
"@babel/runtime": true,
"prop-types": true,
"react": true,
"react-focus-lock>focus-lock": true,
"react-focus-lock>react-clientside-effect": true,
"react-focus-lock>use-callback-ref": true,
"react-focus-lock>use-sidecar": true
}
},
"react-focus-lock>focus-lock": {
"globals": {
"HTMLIFrameElement": true,
"Node.DOCUMENT_FRAGMENT_NODE": true,
"Node.DOCUMENT_NODE": true,
"Node.DOCUMENT_POSITION_CONTAINED_BY": true,
"Node.DOCUMENT_POSITION_CONTAINS": true,
"Node.ELEMENT_NODE": true,
"console.error": true,
"console.warn": true,
"document": true,
"getComputedStyle": true,
"setTimeout": true
},
"packages": {
"wait-on>rxjs>tslib": true
}
},
"react-focus-lock>react-clientside-effect": {
"packages": {
"@babel/runtime": true,
"react": true
}
},
"react-focus-lock>use-callback-ref": {
"packages": {
"react": true
}
},
"react-focus-lock>use-sidecar": {
"globals": {
"console.error": true
},
"packages": {
"react": true,
"react-focus-lock>use-sidecar>detect-node-es": true,
"wait-on>rxjs>tslib": true
}
},
"react-idle-timer": {
"globals": {
"clearTimeout": true,
@ -4200,7 +4217,6 @@
},
"readable-stream": {
"packages": {
"@storybook/api>util-deprecate": true,
"browserify>browser-resolve": true,
"browserify>events": true,
"browserify>process": true,
@ -4210,7 +4226,8 @@
"readable-stream>isarray": true,
"readable-stream>process-nextick-args": true,
"readable-stream>safe-buffer": true,
"readable-stream>string_decoder": true
"readable-stream>string_decoder": true,
"readable-stream>util-deprecate": true
}
},
"readable-stream>core-util-is": {
@ -4233,6 +4250,13 @@
"readable-stream>safe-buffer": true
}
},
"readable-stream>util-deprecate": {
"globals": {
"console.trace": true,
"console.warn": true,
"localStorage": true
}
},
"redux": {
"globals": {
"console": true
@ -4247,6 +4271,7 @@
},
"packages": {
"browserify>process": true,
"browserify>util": true,
"semver>lru-cache": true
}
},
@ -4266,6 +4291,12 @@
"string.prototype.matchall>get-intrinsic": true
}
},
"string.prototype.matchall>es-abstract>is-regex": {
"packages": {
"koa>is-generator-function>has-tostringtag": true,
"string.prototype.matchall>call-bind": true
}
},
"string.prototype.matchall>get-intrinsic": {
"globals": {
"AggregateError": true,
@ -4275,6 +4306,7 @@
"packages": {
"browserify>has": true,
"browserify>has>function-bind": true,
"string.prototype.matchall>es-abstract>has-proto": true,
"string.prototype.matchall>has-symbols": true
}
},

View File

@ -81,22 +81,26 @@
},
"eslint-plugin-jest>@typescript-eslint/utils>eslint-utils": {
"packages": {
"eslint-plugin-jest>@typescript-eslint/utils>eslint-utils>eslint-visitor-keys": true
"eslint>@eslint-community/eslint-utils": true,
"eslint-plugin-jest>@typescript-eslint/utils>eslint-utils>eslint-visitor-keys": true,
"semver": true
}
},
"eslint-plugin-jest>@typescript-eslint/utils": {
"builtin": {
"assert": true,
"path": true
},
"packages": {
"eslint-plugin-jest>@typescript-eslint/experimental-utils>@typescript-eslint/types": true,
"eslint-plugin-jest>@typescript-eslint/utils>eslint-utils": true,
"eslint>@eslint-community/eslint-utils": true,
"eslint-plugin-jest>@typescript-eslint/utils>@typescript-eslint/types": true,
"eslint-plugin-jest>@typescript-eslint/utils>@typescript-eslint/scope-manager": true,
"eslint-plugin-jest>@typescript-eslint/utils>webpack>eslint-scope": true,
"eslint-plugin-mocha>eslint-utils": true,
"@typescript-eslint/parser>@typescript-eslint/types": true,
"eslint": true,
"semver": true,
"@typescript-eslint/parser>@typescript-eslint/scope-manager": true,
"eslint>eslint-scope": true,
"eslint>eslint-utils": true,

File diff suppressed because it is too large Load Diff

View File

@ -73,8 +73,8 @@
"devtools:redux": "remotedev --hostname=localhost --port=8000",
"start:dev": "concurrently -k -n build,react,redux yarn:start yarn:devtools:react yarn:devtools:redux",
"announce": "node development/announcer.js",
"storybook": "start-storybook -p 6006 -c .storybook",
"storybook:build": "build-storybook -c .storybook -o storybook-build",
"storybook": "storybook dev -p 6006 -c .storybook",
"storybook:build": "storybook build -c .storybook -o storybook-build",
"storybook:deploy": "storybook-to-ghpages --existing-output-dir storybook-build --remote storybook --branch master",
"update-changelog": "auto-changelog update",
"generate:migration": "./development/generate-migration.sh",
@ -90,16 +90,22 @@
"ts-migration:dashboard:watch": "yarn ts-migration:dashboard:build --watch",
"ts-migration:enumerate": "ts-node development/ts-migration-dashboard/scripts/write-list-of-files-to-convert.ts",
"test-storybook": "test-storybook -c .storybook",
"test-storybook:ci": "concurrently -k -s first -n \"SB,TEST\" -c \"magenta,blue\" \"yarn storybook:build && npx http-server storybook-build --port 6006 \" \"wait-on tcp:6006 && yarn test-storybook --maxWorkers=2\"",
"test-storybook:ci": "concurrently -k -s first -n \"SB,TEST\" -c \"magenta,blue\" \"yarn storybook:build && npx http-server storybook-build --port 6006 \" \"wait-on tcp:6006 && echo 'Build done. Running storybook tests...' && yarn test-storybook --maxWorkers=2\"",
"githooks:install": "husky install",
"fitness-functions": "ts-node development/fitness-functions/index.ts",
"generate-beta-commit": "node ./development/generate-beta-commit.js"
"generate-beta-commit": "node ./development/generate-beta-commit.js",
"validate-branch-name": "validate-branch-name",
"label-prs": "ts-node ./.github/scripts/label-prs.ts"
},
"resolutions": {
"@babel/core": "patch:@babel/core@npm%3A7.21.5#./.yarn/patches/@babel-core-npm-7.21.5-c72c337956.patch",
"@babel/runtime": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch",
"@types/react": "^16.9.53",
"analytics-node/axios": "^0.21.2",
"ganache-core/lodash": "^4.17.21",
"git-url-parse@^12.0.0": "^13.1.0",
"glob-parent": "^6.0.2",
"globalthis@^1.0.1": "1.0.1",
"netmask": "^2.0.1",
"json-schema": "^0.4.0",
"ast-types": "^0.14.2",
@ -159,26 +165,6 @@
"regenerator-runtime@^0.13.7": "patch:regenerator-runtime@npm%3A0.13.7#./.yarn/patches/regenerator-runtime-npm-0.13.7-41bcbe64ea.patch",
"regenerator-runtime@^0.11.0": "patch:regenerator-runtime@npm%3A0.13.7#./.yarn/patches/regenerator-runtime-npm-0.13.7-41bcbe64ea.patch",
"trim": "^0.0.3",
"@babel/runtime@^7.5.5": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch",
"@babel/runtime@^7.7.6": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch",
"@babel/runtime@^7.9.2": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch",
"@babel/runtime@^7.5.4": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch",
"@babel/runtime@^7.10.3": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch",
"@babel/runtime@^7.1.2": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch",
"@babel/runtime@^7.4.4": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch",
"@babel/runtime@^7.10.2": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch",
"@babel/runtime@^7.4.5": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch",
"@babel/runtime@^7.15.4": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch",
"@babel/runtime@^7.17.8": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch",
"@babel/runtime@^7.8.7": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch",
"@babel/runtime@^7.0.0": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch",
"@babel/runtime@^7.4.0": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch",
"@babel/runtime@^7.3.1": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch",
"@babel/runtime@^7.8.3": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch",
"@babel/runtime@^7.7.2": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch",
"@babel/runtime@^7.12.5": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch",
"@babel/runtime@^7.5.0": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch",
"@babel/runtime@^7.8.4": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch",
"@eslint/eslintrc@^2.0.1": "patch:@eslint/eslintrc@npm%3A2.0.2#./.yarn/patches/@eslint-eslintrc-npm-2.0.2-d308674d86.patch",
"@formatjs/intl-utils@^3.3.1": "patch:@formatjs/intl-utils@npm%3A3.3.1#./.yarn/patches/@formatjs-intl-utils-npm-3.3.1-08510c16ad.patch",
"@fortawesome/fontawesome-free@^5.13.0": "patch:@fortawesome/fontawesome-free@npm%3A5.13.0#./.yarn/patches/@fortawesome-fontawesome-free-npm-5.13.0-f20fc0388d.patch",
@ -208,10 +194,13 @@
"fast-json-patch@^3.1.1": "patch:fast-json-patch@npm%3A3.1.1#./.yarn/patches/fast-json-patch-npm-3.1.1-7e8bb70a45.patch",
"request@^2.83.0": "patch:request@npm%3A2.88.2#./.yarn/patches/request-npm-2.88.2-f4a57c72c4.patch",
"request@^2.88.2": "patch:request@npm%3A2.88.2#./.yarn/patches/request-npm-2.88.2-f4a57c72c4.patch",
"request@^2.85.0": "patch:request@npm%3A2.88.2#./.yarn/patches/request-npm-2.88.2-f4a57c72c4.patch"
"request@^2.85.0": "patch:request@npm%3A2.88.2#./.yarn/patches/request-npm-2.88.2-f4a57c72c4.patch",
"@metamask/assets-controllers@^6.0.0": "patch:@metamask/assets-controllers@npm%3A6.0.0#./.yarn/patches/@metamask-assets-controllers-npm-6.0.0-0cb763bd07.patch"
},
"dependencies": {
"@babel/runtime": "^7.5.5",
"@actions/core": "^1.10.0",
"@actions/github": "^5.1.1",
"@babel/runtime": "^7.18.9",
"@download/blockies": "^1.0.3",
"@ensdomains/content-hash": "^2.5.6",
"@ethereumjs/common": "^3.1.1",
@ -227,11 +216,14 @@
"@keystonehq/metamask-airgapped-keyring": "^0.9.2",
"@lavamoat/snow": "^1.5.0",
"@material-ui/core": "^4.11.0",
"@metamask-institutional/extension": "^0.1.3",
"@metamask-institutional/portfolio-dashboard": "^1.1.3",
"@metamask/address-book-controller": "^2.0.0",
"@metamask/announcement-controller": "^3.0.0",
"@metamask/approval-controller": "^2.1.0",
"@metamask/assets-controllers": "^6.0.0",
"@metamask/assets-controllers": "^7.0.0",
"@metamask/base-controller": "^2.0.0",
"@metamask/browser-passworder": "^4.1.0",
"@metamask/contract-metadata": "^2.3.1",
"@metamask/controller-utils": "^3.3.0",
"@metamask/design-tokens": "^1.9.0",
@ -244,7 +236,7 @@
"@metamask/eth-token-tracker": "^4.0.0",
"@metamask/eth-trezor-keyring": "^1.0.0",
"@metamask/etherscan-link": "^2.2.0",
"@metamask/gas-fee-controller": "^4.0.0",
"@metamask/gas-fee-controller": "^5.0.0",
"@metamask/jazzicon": "^2.0.0",
"@metamask/key-tree": "^7.0.0",
"@metamask/logo": "^3.1.1",
@ -252,24 +244,24 @@
"@metamask/metamask-eth-abis": "^3.0.0",
"@metamask/notification-controller": "^2.0.0",
"@metamask/obs-store": "^8.1.0",
"@metamask/permission-controller": "^3.1.0",
"@metamask/permission-controller": "^3.2.0",
"@metamask/phishing-controller": "^3.0.0",
"@metamask/post-message-stream": "^6.0.0",
"@metamask/providers": "^10.2.1",
"@metamask/rate-limit-controller": "^2.0.0",
"@metamask/rpc-methods": "^0.32.2",
"@metamask/rpc-methods-flask": "npm:@metamask/rpc-methods@0.32.2",
"@metamask/rpc-methods-flask": "npm:@metamask/rpc-methods@0.33.1-flask.1",
"@metamask/safe-event-emitter": "^2.0.0",
"@metamask/scure-bip39": "^2.0.3",
"@metamask/signature-controller": "^1.0.0",
"@metamask/signature-controller": "^2.0.0",
"@metamask/slip44": "^3.0.0",
"@metamask/smart-transactions-controller": "^3.1.0",
"@metamask/snaps-controllers": "^0.32.2",
"@metamask/snaps-controllers-flask": "npm:@metamask/snaps-controllers@0.32.2",
"@metamask/snaps-controllers-flask": "npm:@metamask/snaps-controllers@0.33.1-flask.1",
"@metamask/snaps-ui": "^0.32.2",
"@metamask/snaps-ui-flask": "npm:@metamask/snaps-ui@0.32.2",
"@metamask/snaps-ui-flask": "npm:@metamask/snaps-ui@0.33.1-flask.1",
"@metamask/snaps-utils": "^0.32.2",
"@metamask/snaps-utils-flask": "npm:@metamask/snaps-utils@0.32.2",
"@metamask/snaps-utils-flask": "npm:@metamask/snaps-utils@0.33.1-flask.1",
"@metamask/subject-metadata-controller": "^2.0.0",
"@metamask/swappable-obj-proxy": "^2.1.0",
"@metamask/utils": "^5.0.0",
@ -317,6 +309,7 @@
"fuse.js": "^3.2.0",
"globalthis": "^1.0.1",
"human-standard-token-abi": "^2.0.0",
"husky": "^8.0.3",
"immer": "^9.0.6",
"is-retry-allowed": "^2.2.0",
"jest-junit": "^14.0.1",
@ -339,6 +332,7 @@
"qrcode.react": "^1.0.1",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-focus-lock": "^2.9.4",
"react-idle-timer": "^4.2.5",
"react-inspector": "^2.3.0",
"react-markdown": "^6.0.3",
@ -365,7 +359,7 @@
},
"devDependencies": {
"@babel/code-frame": "^7.12.13",
"@babel/core": "^7.12.1",
"@babel/core": "^7.21.5",
"@babel/eslint-parser": "^7.13.14",
"@babel/eslint-plugin": "^7.12.1",
"@babel/preset-env": "^7.5.5",
@ -386,22 +380,21 @@
"@metamask/phishing-warning": "^2.1.0",
"@metamask/test-dapp": "^6.0.0",
"@sentry/cli": "^1.58.0",
"@storybook/addon-a11y": "^6.5.13",
"@storybook/addon-actions": "^6.5.13",
"@storybook/addon-essentials": "^6.5.13",
"@storybook/addon-knobs": "^6.4.0",
"@storybook/addons": "^6.5.13",
"@storybook/api": "^6.5.13",
"@storybook/builder-webpack5": "^6.5.13",
"@storybook/client-api": "^6.5.13",
"@storybook/components": "^6.5.13",
"@storybook/core": "^6.5.13",
"@storybook/core-events": "^6.5.13",
"@storybook/manager-webpack5": "^6.5.13",
"@storybook/react": "^6.5.13",
"@storybook/addon-a11y": "^7.0.11",
"@storybook/addon-actions": "^7.0.11",
"@storybook/addon-essentials": "^7.0.11",
"@storybook/addon-knobs": "^7.0.2",
"@storybook/addon-mdx-gfm": "^7.0.11",
"@storybook/addons": "^7.0.11",
"@storybook/api": "^7.0.11",
"@storybook/client-api": "^7.0.11",
"@storybook/components": "^7.0.11",
"@storybook/core-events": "^7.0.11",
"@storybook/react": "^7.0.11",
"@storybook/react-webpack5": "^7.0.11",
"@storybook/storybook-deployer": "^2.8.16",
"@storybook/test-runner": "^0.9.2",
"@storybook/theming": "^6.5.13",
"@storybook/test-runner": "^0.10.0",
"@storybook/theming": "^7.0.11",
"@testing-library/jest-dom": "^5.11.10",
"@testing-library/react": "^10.4.8",
"@testing-library/react-hooks": "^8.0.1",
@ -433,7 +426,7 @@
"@types/yargs": "^17.0.8",
"@typescript-eslint/eslint-plugin": "^5.30.7",
"@typescript-eslint/parser": "^5.30.7",
"@whitespace/storybook-addon-html": "^5.1.1",
"@whitespace/storybook-addon-html": "^5.1.4",
"addons-linter": "^5.2.0",
"babel-plugin-module-resolver": "^5.0.0",
"babelify": "^10.0.0",
@ -466,7 +459,7 @@
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.23.1",
"eslint-plugin-react-hooks": "^4.2.0",
"eslint-plugin-storybook": "^0.6.4",
"eslint-plugin-storybook": "^0.6.12",
"fancy-log": "^1.3.3",
"fast-glob": "^3.2.2",
"fs-extra": "^8.1.0",
@ -523,7 +516,6 @@
"read-installed": "^4.0.3",
"redux-mock-store": "^1.5.4",
"remote-redux-devtools": "^0.5.16",
"require-from-string": "^2.0.2",
"resolve-url-loader": "^3.1.5",
"sass": "^1.32.4",
"sass-loader": "^10.1.1",
@ -534,7 +526,8 @@
"source-map": "^0.7.2",
"source-map-explorer": "^2.4.2",
"squirrelly": "^8.0.8",
"storybook-dark-mode": "^1.1.0",
"storybook": "^7.0.11",
"storybook-dark-mode": "^3.0.0",
"stream-browserify": "^3.0.0",
"string.prototype.matchall": "^4.0.2",
"style-loader": "^0.21.0",
@ -576,6 +569,7 @@
"@metamask/eth-ledger-bridge-keyring>hdkey>secp256k1": false,
"@storybook/api>core-js": false,
"@storybook/core>@storybook/core-client>@storybook/ui>core-js-pure": false,
"@storybook/test-runner>@storybook/core-common>esbuild": false,
"eth-json-rpc-filters>eth-json-rpc-middleware>ethereumjs-util>keccak": false,
"eth-json-rpc-filters>eth-json-rpc-middleware>ethereumjs-util>secp256k1": false,
"eth-json-rpc-middleware>eth-sig-util>ethereumjs-util>keccak": false,
@ -620,7 +614,10 @@
"@metamask/eth-trezor-keyring>@trezor/connect-web>@trezor/connect>@trezor/transport>protobufjs": false,
"@metamask/eth-trezor-keyring>@trezor/connect-web>@trezor/connect>@trezor/utxo-lib>blake-hash": false,
"@metamask/eth-trezor-keyring>@trezor/connect-web>@trezor/connect>@trezor/utxo-lib>tiny-secp256k1": false,
"@metamask/eth-trezor-keyring>hdkey>secp256k1": false
"@metamask/eth-trezor-keyring>hdkey>secp256k1": false,
"@storybook/addon-knobs>core-js": false,
"@storybook/manager-webpack5>core-js": false,
"@storybook/react-webpack5>@storybook/preset-react-webpack>@pmmmwh/react-refresh-webpack-plugin>core-js-pure": false
}
},
"packageManager": "yarn@3.2.4"

View File

@ -583,7 +583,10 @@ export enum MetaMetricsEventName {
WalletSetupFailed = 'Wallet Setup Failed',
WalletCreated = 'Wallet Created',
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
UserClickedDeepLink = 'User clicked deeplink',
UserClickedDeepLink = 'User Clicked Deeplink',
UserClickedConnectCustodialAccount = 'Clicked Connect Custodial Account',
UserClickedPortfolioButton = 'Clicked Portfolio Button',
UserClickedCompliance = 'Clicked Compliance',
///: END:ONLY_INCLUDE_IN
AccountDetailMenuOpened = 'Account Details Menu Opened',
BlockExplorerLinkClicked = 'Block Explorer Clicked',

View File

@ -203,7 +203,7 @@ export const LOCALHOST_RPC_URL = 'http://localhost:8545';
*/
export const CURRENCY_SYMBOLS = {
ARBITRUM: 'ETH',
AURORA: 'Aurora ETH',
AURORA_ETH: 'AURORA ETH',
AVALANCHE: 'AVAX',
BNB: 'BNB',
BUSD: 'BUSD',
@ -381,6 +381,7 @@ export const NATIVE_CURRENCY_TOKEN_IMAGE_MAP = {
[CURRENCY_SYMBOLS.AVALANCHE]: AVAX_TOKEN_IMAGE_URL,
[CURRENCY_SYMBOLS.OPTIMISM]: OPTIMISM_TOKEN_IMAGE_URL,
[CURRENCY_SYMBOLS.CELO]: CELO_TOKEN_IMAGE_URL,
[CURRENCY_SYMBOLS.AURORA_ETH]: ETH_TOKEN_IMAGE_URL,
} as const;
export const INFURA_BLOCKED_KEY = 'countryBlocked';
@ -575,7 +576,7 @@ export const FEATURED_RPCS: RPCDefinition[] = [
chainId: CHAIN_IDS.AURORA,
nickname: AURORA_DISPLAY_NAME,
rpcUrl: `https://aurora-mainnet.infura.io/v3/${infuraProjectId}`,
ticker: CURRENCY_SYMBOLS.AURORA,
ticker: CURRENCY_SYMBOLS.AURORA_ETH,
rpcPrefs: {
blockExplorerUrl: 'https://aurorascan.dev/',
imageUrl: AURORA_TOKEN_IMAGE_URL,

View File

@ -130,8 +130,7 @@ export const WETH_ARBITRUM_CONTRACT_ADDRESS =
const SWAPS_TESTNET_CHAIN_ID = '0x539';
export const SWAPS_API_V2_BASE_URL = 'https://swap.metaswap.codefi.network';
export const SWAPS_DEV_API_V2_BASE_URL =
'https://swap.metaswap-dev.codefi.network';
export const SWAPS_DEV_API_V2_BASE_URL = 'https://swap.dev-api.cx.metamask.io';
export const GAS_API_BASE_URL = 'https://gas-api.metaswap.codefi.network';
export const GAS_DEV_API_BASE_URL =
'https://gas-api.metaswap-dev.codefi.network';

View File

@ -14,6 +14,16 @@ export function isBurnAddress(address: string) {
return address === BURN_ADDRESS;
}
export function isEmptyHexString(value: string): boolean {
return [
undefined,
null,
'0x',
'0x0',
'0x0000000000000000000000000000000000000000000000000000000000000000',
].includes(value);
}
/**
* Validates that the input is a hex address. This utility method is a thin
* wrapper around ethereumjs-util.isValidAddress, with the exception that it

View File

@ -73,6 +73,10 @@ describe('network utils', () => {
expect(isTokenDetectionEnabledForNetwork('0xa86a')).toBe(true);
});
it('returns true given the chain ID for Aurora', () => {
expect(isTokenDetectionEnabledForNetwork('0x4e454152')).toBe(true);
});
it('returns false given a string that is not the chain ID for Mainnet, BSC, Polygon, or Avalanche', () => {
expect(isTokenDetectionEnabledForNetwork('some other chain ID')).toBe(
false,

View File

@ -39,6 +39,7 @@ export function isTokenDetectionEnabledForNetwork(chainId: string | undefined) {
case CHAIN_IDS.BSC:
case CHAIN_IDS.POLYGON:
case CHAIN_IDS.AVALANCHE:
case CHAIN_IDS.AURORA:
return true;
default:
return false;

View File

@ -65,6 +65,7 @@ function documentElementCheck() {
*/
function blockedDomainCheck() {
const blockedDomains = [
'execution.metamask.io',
'uscourts.gov',
'dropbox.com',
'webbyawards.com',

View File

@ -120,7 +120,8 @@
"networkConfigurations": {
"testNetworkConfigurationId": {
"rpcUrl": "https://testrpc.com",
"chainId": "0x1"
"chainId": "0x1",
"nickname": "Custom Mainnet RPC"
}
},
"keyrings": [

View File

@ -391,10 +391,132 @@ const openDapp = async (driver, contract = null, dappURL = DAPP_URL) => {
? await driver.openNewPage(`${dappURL}/?contract=${contract}`)
: await driver.openNewPage(dappURL);
};
const STALELIST_URL =
'https://static.metafi.codefi.network/api/v1/lists/stalelist.json';
const emptyHtmlPage = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>title</title>
</head>
<body>
Empty page
</body>
</html>`;
/**
* Setup fetch mocks for the phishing detection feature.
*
* The mock configuration will show that "127.0.0.1" is blocked. The dynamic lookup on the warning
* page can be customized, so that we can test both the MetaMask and PhishFort block cases.
*
* @param {import('mockttp').Mockttp} mockServer - The mock server.
* @param {object} metamaskPhishingConfigResponse - The response for the dynamic phishing
* configuration lookup performed by the warning page.
*/
async function setupPhishingDetectionMocks(
mockServer,
metamaskPhishingConfigResponse,
) {
await mockServer.forGet(STALELIST_URL).thenCallback(() => {
return {
statusCode: 200,
json: {
version: 2,
tolerance: 2,
fuzzylist: [],
allowlist: [],
blocklist: ['127.0.0.1'],
lastUpdated: 0,
},
};
});
await mockServer
.forGet('https://github.com/MetaMask/eth-phishing-detect/issues/new')
.thenCallback(() => {
return {
statusCode: 200,
body: emptyHtmlPage,
};
});
await mockServer
.forGet('https://github.com/phishfort/phishfort-lists/issues/new')
.thenCallback(() => {
return {
statusCode: 200,
body: emptyHtmlPage,
};
});
await mockServer
.forGet(
'https://raw.githubusercontent.com/MetaMask/eth-phishing-detect/master/src/config.json',
)
.thenCallback(() => metamaskPhishingConfigResponse);
}
function mockPhishingDetection(mockServer) {
setupPhishingDetectionMocks(mockServer, {
statusCode: 200,
json: {
version: 2,
tolerance: 2,
fuzzylist: [],
whitelist: [],
blacklist: ['127.0.0.1'],
lastUpdated: 0,
},
});
}
const PRIVATE_KEY =
'0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC';
const generateETHBalance = (eth) => convertToHexValue(eth * 10 ** 18);
const defaultGanacheOptions = {
accounts: [{ secretKey: PRIVATE_KEY, balance: generateETHBalance(25) }],
};
const SERVICE_WORKER_URL = 'chrome://inspect/#service-workers';
const sendTransaction = async (driver, recipientAddress, quantity) => {
await driver.clickElement('[data-testid="eth-overview-send"]');
await driver.fill('[data-testid="ens-input"]', recipientAddress);
await driver.fill('.unit-input__input', quantity);
await driver.clickElement('[data-testid="page-container-footer-next"]');
await driver.clickElement('[data-testid="page-container-footer-next"]');
await driver.clickElement('[data-testid="home__activity-tab"]');
await driver.findElement('.transaction-list-item');
};
const findAnotherAccountFromAccountList = async (
driver,
itemNumber,
accountName,
) => {
await driver.clickElement('.account-menu__icon');
const accountMenuItemSelector = `.account-menu__account:nth-child(${itemNumber})`;
const fourthAccountName = await driver.findElement(
`${accountMenuItemSelector} .account-menu__name`,
);
assert.equal(await fourthAccountName.getText(), accountName);
return accountMenuItemSelector;
};
const TEST_SEED_PHRASE =
'forum vessel pink push lonely enact gentle tail admit parrot grunt dress';
const TEST_SEED_PHRASE_TWO =
'phrase upgrade clock rough situate wedding elder clever doctor stamp excess tent';
module.exports = {
DAPP_URL,
DAPP_ONE_URL,
SERVICE_WORKER_URL,
TEST_SEED_PHRASE,
TEST_SEED_PHRASE_TWO,
getWindowHandles,
convertToHexValue,
tinyDelayMs,
@ -410,4 +532,9 @@ module.exports = {
importWrongSRPOnboardingFlow,
testSRPDropdownIterations,
openDapp,
mockPhishingDetection,
setupPhishingDetectionMocks,
defaultGanacheOptions,
sendTransaction,
findAnotherAccountFromAccountList,
};

View File

@ -4,6 +4,7 @@ const path = require('path');
const enLocaleMessages = require('../../app/_locales/en/messages.json');
const createStaticServer = require('../../development/create-static-server');
const {
TEST_SEED_PHRASE_TWO,
tinyDelayMs,
regularDelayMs,
largeDelayMs,
@ -21,9 +22,6 @@ describe('MetaMask', function () {
let dappServer;
let tokenAddress;
const testSeedPhrase =
'phrase upgrade clock rough situate wedding elder clever doctor stamp excess tent';
this.bail(true);
let failed = false;
@ -151,7 +149,7 @@ describe('MetaMask', function () {
await driver.pasteIntoField(
'[data-testid="import-srp__srp-word-0"]',
testSeedPhrase,
TEST_SEED_PHRASE_TWO,
);
await driver.fill('#password', 'correct horse battery staple');
@ -430,7 +428,7 @@ describe('MetaMask', function () {
it('checks balance', async function () {
await driver.clickElement({
text: 'Assets',
text: 'Tokens',
tag: 'button',
});

View File

@ -1,5 +1,10 @@
const { strict: assert } = require('assert');
const { convertToHexValue, withFixtures, openDapp } = require('../helpers');
const {
convertToHexValue,
withFixtures,
openDapp,
SERVICE_WORKER_URL,
} = require('../helpers');
const FixtureBuilder = require('../fixture-builder');
describe('MV3 - Dapp interactions', function () {
@ -34,7 +39,7 @@ describe('MV3 - Dapp interactions', function () {
await openDapp(driver);
// Terminate Service Worker
await driver.openNewPage('chrome://inspect/#service-workers/');
await driver.openNewPage(SERVICE_WORKER_URL);
await driver.clickElement({
text: 'Service workers',
tag: 'button',

View File

@ -0,0 +1,52 @@
const { strict: assert } = require('assert');
const {
withFixtures,
mockPhishingDetection,
SERVICE_WORKER_URL,
openDapp,
defaultGanacheOptions,
} = require('../helpers');
const FixtureBuilder = require('../fixture-builder');
describe('Phishing warning page', function () {
it('should restore the transaction when service worker restarts', async function () {
await withFixtures(
{
dapp: true,
fixtures: new FixtureBuilder().build(),
ganacheOptions: defaultGanacheOptions,
title: this.test.title,
testSpecificMock: mockPhishingDetection,
},
async ({ driver }) => {
await driver.navigate();
// log in wallet
await driver.fill('#password', 'correct horse battery staple');
await driver.press('#password', driver.Key.ENTER);
// Restart service worker
await driver.openNewPage(SERVICE_WORKER_URL);
await driver.clickElement({
text: 'Service workers',
tag: 'button',
});
await driver.clickElement({
text: 'terminate',
tag: 'span',
});
// Open the dapp site and extension detect it as phishing warning page
await openDapp(driver);
await driver.switchToWindowWithTitle('MetaMask Phishing Detection');
const phishingPageHeader = await driver.findElements({
text: 'Deceptive site ahead',
tag: 'h1',
});
assert.ok(phishingPageHeader.length, 1);
},
);
});
});

View File

@ -1,5 +1,12 @@
const { strict: assert } = require('assert');
const { convertToHexValue, withFixtures, openDapp } = require('../helpers');
const {
convertToHexValue,
withFixtures,
openDapp,
SERVICE_WORKER_URL,
defaultGanacheOptions,
} = require('../helpers');
const FixtureBuilder = require('../fixture-builder');
const {
ACTION_QUEUE_METRICS_E2E_TEST,
@ -9,14 +16,6 @@ const {
MetaMetricsEventCategory,
} = require('../../../shared/constants/metametrics');
const PRIVATE_KEY =
'0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC';
const generateETHBalance = (eth) => convertToHexValue(eth * 10 ** 18);
const defaultGanacheOptions = {
accounts: [{ secretKey: PRIVATE_KEY, balance: generateETHBalance(25) }],
};
const numberOfSegmentRequests = 3;
async function mockSegment(mockServer) {
@ -76,7 +75,7 @@ describe('MV3 - Service worker restart', function () {
await driver.clickElement({ text: 'Create', tag: 'button' });
await driver.openNewPage('chrome://inspect/#service-workers/');
await driver.openNewPage(SERVICE_WORKER_URL);
await driver.clickElement({
text: 'Service workers',
tag: 'button',
@ -159,7 +158,7 @@ describe('MV3 - Service worker restart', function () {
// Restart service worker in a new window
// Because if we stay in the same window we will lose the popup when opening a new tab
await driver.switchToNewWindow();
await driver.openNewURL('chrome://inspect/#service-workers');
await driver.openNewURL(SERVICE_WORKER_URL);
windowHandles = await driver.getAllWindowHandles();
// MM expanded view, Dapp, Notification popup, console and service worker
await driver.waitUntilXWindowHandles(5);

View File

@ -1,3 +1,3 @@
module.exports = {
TEST_SNAPS_WEBSITE_URL: 'https://metamask.github.io/test-snaps/5.2.0/',
TEST_SNAPS_WEBSITE_URL: 'https://metamask.github.io/test-snaps/5.5.0/',
};

View File

@ -0,0 +1,91 @@
const { withFixtures } = require('../helpers');
const FixtureBuilder = require('../fixture-builder');
const { TEST_SNAPS_WEBSITE_URL } = require('./enums');
describe('Test Snap ethereum_provider', function () {
it('can use the ethereum_provider endowment', async function () {
const ganacheOptions = {
accounts: [
{
secretKey:
'0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC',
balance: 25000000000000000000,
},
],
};
await withFixtures(
{
fixtures: new FixtureBuilder().build(),
ganacheOptions,
failOnConsoleError: false,
title: this.test.title,
},
async ({ driver }) => {
await driver.navigate();
// enter pw into extension
await driver.fill('#password', 'correct horse battery staple');
await driver.press('#password', driver.Key.ENTER);
// navigate to test snaps page and connect
await driver.driver.get(TEST_SNAPS_WEBSITE_URL);
await driver.delay(1000);
const snapButton = await driver.findElement('#connectEthproviderSnap');
await driver.scrollToElement(snapButton);
await driver.delay(1000);
await driver.clickElement('#connectEthproviderSnap');
await driver.delay(1000);
// switch to metamask extension and click connect
const windowHandles = await driver.waitUntilXWindowHandles(
2,
1000,
10000,
);
await driver.switchToWindowWithTitle(
'MetaMask Notification',
windowHandles,
);
await driver.clickElement({
text: 'Connect',
tag: 'button',
});
await driver.waitForSelector({ text: 'Approve & install' });
await driver.clickElement({
text: 'Approve & install',
tag: 'button',
});
await driver.waitForSelector({ text: 'Ok' });
await driver.clickElement({
text: 'Ok',
tag: 'button',
});
// click send inputs on test snap page
await driver.switchToWindowWithTitle('Test Snaps', windowHandles);
// wait for npm installation success
await driver.waitForSelector({
css: '#connectEthproviderSnap',
text: 'Reconnect to ethereum-provider Snap',
});
// find and click on send test
const snapButton2 = await driver.findElement('#sendEthprovider');
await driver.scrollToElement(snapButton2);
await driver.delay(500);
await driver.clickElement('#sendEthprovider');
// check the results of the message signature using waitForSelector
await driver.waitForSelector({
css: '#ethproviderResult',
text: 'true',
});
},
);
});
});

View File

@ -0,0 +1,108 @@
const { withFixtures } = require('../helpers');
const FixtureBuilder = require('../fixture-builder');
const { TEST_SNAPS_WEBSITE_URL } = require('./enums');
describe('Test Snap getEntropy', function () {
it('can use snap_getEntropy inside a snap', async function () {
const ganacheOptions = {
accounts: [
{
secretKey:
'0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC',
balance: 25000000000000000000,
},
],
};
await withFixtures(
{
fixtures: new FixtureBuilder().build(),
ganacheOptions,
failOnConsoleError: false,
title: this.test.title,
},
async ({ driver }) => {
await driver.navigate();
// enter pw into extension
await driver.fill('#password', 'correct horse battery staple');
await driver.press('#password', driver.Key.ENTER);
// navigate to test snaps page and connect
await driver.driver.get(TEST_SNAPS_WEBSITE_URL);
await driver.delay(1000);
const snapButton = await driver.findElement('#connectGetEntropySnap');
await driver.scrollToElement(snapButton);
await driver.delay(1000);
await driver.clickElement('#connectGetEntropySnap');
await driver.delay(1000);
// switch to metamask extension and click connect
let windowHandles = await driver.waitUntilXWindowHandles(
2,
1000,
10000,
);
await driver.switchToWindowWithTitle(
'MetaMask Notification',
windowHandles,
);
await driver.clickElement({
text: 'Connect',
tag: 'button',
});
await driver.waitForSelector({ text: 'Approve & install' });
await driver.clickElement({
text: 'Approve & install',
tag: 'button',
});
await driver.waitForSelector({ text: 'Ok' });
await driver.clickElement({
text: 'Ok',
tag: 'button',
});
// click send inputs on test snap page
await driver.switchToWindowWithTitle('Test Snaps', windowHandles);
// wait for npm installation success
await driver.waitForSelector({
css: '#connectGetEntropySnap',
text: 'Reconnect to getEntropy Snap',
});
// find and click on send test
await driver.pasteIntoField('#entropyMessage', '1234');
await driver.delay(500);
const snapButton2 = await driver.findElement('#signEntropyMessage');
await driver.scrollToElement(snapButton2);
await driver.delay(500);
await driver.clickElement('#signEntropyMessage');
// Switch to approve signature message window and approve
windowHandles = await driver.waitUntilXWindowHandles(2, 1000, 10000);
await driver.switchToWindowWithTitle(
'MetaMask Notification',
windowHandles,
);
await driver.clickElement({
text: 'Approve',
tag: 'button',
});
// switch back to test-snaps page
windowHandles = await driver.waitUntilXWindowHandles(1, 1000, 10000);
await driver.switchToWindowWithTitle('Test Snaps', windowHandles);
// check the results of the message signature using waitForSelector
await driver.waitForSelector({
css: '#entropySignResult',
text: '"0xb9c20d675976e12c8bb53c3fd8fdff2dee11ad2b132eb453b5a8f35b0553c52d3bcac0fd3324d22ff0c53b3445ef48c119ba6435bc9bfb03234806719599aa6f6245593238c734bcf9d94d2873cacdd65a3176be3ae7e5b84f95fdd4487a395f"',
});
},
);
});
});

View File

@ -0,0 +1,106 @@
const { strict: assert } = require('assert');
const { withFixtures } = require('../helpers');
const FixtureBuilder = require('../fixture-builder');
const { TEST_SNAPS_WEBSITE_URL } = require('./enums');
describe('Test Snap networkAccess', function () {
it('test the network-access endowment', async function () {
const ganacheOptions = {
accounts: [
{
secretKey:
'0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC',
balance: 25000000000000000000,
},
],
};
await withFixtures(
{
fixtures: new FixtureBuilder().build(),
ganacheOptions,
failOnConsoleError: false,
title: this.test.title,
},
async ({ driver }) => {
await driver.navigate();
// enter pw into extension
await driver.fill('#password', 'correct horse battery staple');
await driver.press('#password', driver.Key.ENTER);
// navigate to test snaps page and connect to dialog snap
await driver.openNewPage(TEST_SNAPS_WEBSITE_URL);
await driver.delay(1000);
const dialogButton = await driver.findElement(
'#connectNetworkAccessSnap',
);
await driver.scrollToElement(dialogButton);
await driver.delay(1000);
await driver.clickElement('#connectNetworkAccessSnap');
await driver.delay(1000);
// switch to metamask extension and click connect
let windowHandles = await driver.waitUntilXWindowHandles(
3,
1000,
10000,
);
await driver.switchToWindowWithTitle(
'MetaMask Notification',
windowHandles,
);
await driver.clickElement({
text: 'Connect',
tag: 'button',
});
await driver.waitForSelector({ text: 'Approve & install' });
await driver.clickElement({
text: 'Approve & install',
tag: 'button',
});
await driver.waitForSelector({ text: 'Ok' });
await driver.clickElement({
text: 'Ok',
tag: 'button',
});
// switch to test snaps tab
await driver.switchToWindowWithTitle('Test Snaps', windowHandles);
// wait for npm installation success
await driver.waitForSelector({
css: '#connectNetworkAccessSnap',
text: 'Reconnect to networkAccess Snap',
});
// click on alert dialog
await driver.clickElement('#sendNetworkAccessTest');
await driver.delay(500);
// switch to dialog popup
windowHandles = await driver.waitUntilXWindowHandles(3, 1000, 10000);
await driver.switchToWindowWithTitle(
'MetaMask Notification',
windowHandles,
);
await driver.delay(500);
// check dialog contents
const result = await driver.findElement('.snap-ui-renderer__panel');
await driver.scrollToElement(result);
await driver.delay(500);
assert.equal(await result.getText(), 'FETCHED_SUCCESSFULLY');
// click ok button
await driver.clickElement({
text: 'Ok',
tag: 'button',
});
},
);
});
});

View File

@ -3,10 +3,7 @@ const FixtureBuilder = require('../fixture-builder');
const { TEST_SNAPS_WEBSITE_URL } = require('./enums');
describe('Test Snap RPC', function () {
// Disabled for now due to a bug.
// TODO: Re-enable when fixed.
// eslint-disable-next-line mocha/no-skipped-tests
it.skip('can use the cross-snap RPC endowment and produce a public key', async function () {
it('can use the cross-snap RPC endowment and produce a public key', async function () {
const ganacheOptions = {
accounts: [
{

View File

@ -1,16 +1,17 @@
const { strict: assert } = require('assert');
const {
TEST_SEED_PHRASE,
convertToHexValue,
withFixtures,
regularDelayMs,
completeImportSRPOnboardingFlow,
sendTransaction,
findAnotherAccountFromAccountList,
} = require('../helpers');
const enLocaleMessages = require('../../../app/_locales/en/messages.json');
const FixtureBuilder = require('../fixture-builder');
describe('Add account', function () {
const testSeedPhrase =
'forum vessel pink push lonely enact gentle tail admit parrot grunt dress';
const testPassword = 'correct horse battery staple';
const ganacheOptions = {
accounts: [
@ -21,8 +22,8 @@ describe('Add account', function () {
},
],
};
const firstAccount = '0x0Cc5261AB8cE458dc977078A3623E2BaDD27afD3';
const secondAccount = '0x3ED0eE22E0685Ebbf07b2360A8331693c413CC59';
const thirdAccount = '0xD38d853771Fb546bd8B18b2F3638491bC0B0E906';
it('should display correct new account name after create', async function () {
await withFixtures(
@ -50,7 +51,7 @@ describe('Add account', function () {
);
});
it('should add the same account addresses when a secret recovery phrase is imported, the account is locked, and the same secret recovery phrase is imported again', async function () {
it('should not affect public address when using secret recovery phrase to recover account with non-zero balance', async function () {
await withFixtures(
{
fixtures: new FixtureBuilder({ onboarding: true }).build(),
@ -61,64 +62,40 @@ describe('Add account', function () {
async ({ driver }) => {
await driver.navigate();
// On boarding with 1st account
await completeImportSRPOnboardingFlow(
driver,
testSeedPhrase,
TEST_SEED_PHRASE,
testPassword,
);
await driver.clickElement('.account-menu__icon');
// Check address of 1st account
const firstAccountPublicAddress = await checkAccountDetails(driver);
assert.equal(firstAccountPublicAddress, firstAccount);
await driver.delay(regularDelayMs);
// Create a new account
await driver.findClickableElement('.account-menu__icon');
await driver.clickElement('[data-testid="account-menu-icon"]');
await driver.clickElement({ text: 'Create account', tag: 'div' });
await driver.fill('.new-account-create-form input', '2nd account');
await driver.clickElement({ text: 'Create', tag: 'button' });
await driver.clickElement(
'[data-testid="account-options-menu-button"]',
);
await driver.clickElement(
'[data-testid="account-options-menu__account-details"]',
// Check address of 2nd account
const secondAccountPublicAddress = await checkAccountDetails(driver);
assert.strictEqual(secondAccountPublicAddress, secondAccount);
await driver.delay(regularDelayMs);
// Give 2nd locally account some balance so it will not be removed after recovering SRP
const accountOneSelector = await findAnotherAccountFromAccountList(
driver,
1,
'Account 1',
);
await driver.clickElement(accountOneSelector);
await sendTransaction(driver, secondAccount, '2.8');
const detailsModal = await driver.findVisibleElement('span .modal');
// get the public address for the "second account"
await driver.waitForSelector('.qr-code__address');
const secondAccountAddress = await driver.findElement({
text: secondAccount,
tag: 'div',
});
const secondAccountPublicAddress = await secondAccountAddress.getText();
await driver.clickElement('.account-modal__close');
await detailsModal.waitForElementState('hidden');
// generate a third accound
await driver.clickElement('.account-menu__icon');
await driver.clickElement({ text: 'Create account', tag: 'div' });
await driver.fill('.new-account-create-form input', '3rd account');
await driver.clickElement({ text: 'Create', tag: 'button' });
await driver.clickElement(
'[data-testid="account-options-menu-button"]',
);
await driver.clickElement(
'[data-testid="account-options-menu__account-details"]',
);
// get the public address for the "third account"
const secondDetailsModal = await driver.findVisibleElement(
'span .modal',
);
await driver.waitForSelector('.qr-code__address');
const thirdAccountAddress = await driver.findElement({
text: thirdAccount,
tag: 'div',
});
const thirdAccountPublicAddress = await thirdAccountAddress.getText();
await driver.clickElement('.account-modal__close');
await secondDetailsModal.waitForElementState('hidden');
// lock account
// Lock the account
await driver.clickElement('.account-menu__icon');
await driver.delay(regularDelayMs);
@ -128,7 +105,7 @@ describe('Add account', function () {
await lockButton.click();
await driver.delay(regularDelayMs);
// restore same seed phrase
// Recover via SRP in "forget password" option
const restoreSeedLink = await driver.findClickableElement(
'.unlock-page__link',
);
@ -138,7 +115,7 @@ describe('Add account', function () {
await driver.pasteIntoField(
'[data-testid="import-srp__srp-word-0"]',
testSeedPhrase,
TEST_SEED_PHRASE,
);
await driver.fill('#password', 'correct horse battery staple');
@ -147,59 +124,27 @@ describe('Add account', function () {
text: enLocaleMessages.restore.message,
tag: 'button',
});
// Land in 1st account home page
await driver.findElement('.home__main-view');
// Check address of 1st account
const restoredFirstAccountPublicAddress = await checkAccountDetails(
driver,
);
assert.equal(restoredFirstAccountPublicAddress, firstAccount);
await driver.delay(regularDelayMs);
// recreate a "2nd account"
await driver.clickElement('.account-menu__icon');
await driver.clickElement({ text: 'Create account', tag: 'div' });
await driver.fill('.new-account-create-form input', '2nd account');
await driver.clickElement({ text: 'Create', tag: 'button' });
await driver.clickElement(
'[data-testid="account-options-menu-button"]',
// Check address of 2nd account
const accountTwoSelector = await findAnotherAccountFromAccountList(
driver,
2,
'Account 2',
);
await driver.clickElement(
'[data-testid="account-options-menu__account-details"]',
);
const thirdDetailsModal = await driver.findVisibleElement(
'span .modal',
);
// get the public address for the "second account"
await driver.waitForSelector('.qr-code__address');
const recreatedSecondAccountAddress = await driver.findElement({
text: secondAccount,
tag: 'div',
});
assert.equal(
await recreatedSecondAccountAddress.getText(),
secondAccountPublicAddress,
);
await driver.clickElement('.account-modal__close');
await thirdDetailsModal.waitForElementState('hidden');
// re-generate a third accound
await driver.clickElement('.account-menu__icon');
await driver.clickElement({ text: 'Create account', tag: 'div' });
await driver.fill('.new-account-create-form input', '3rd account');
await driver.clickElement({ text: 'Create', tag: 'button' });
await driver.clickElement(
'[data-testid="account-options-menu-button"]',
);
await driver.clickElement(
'[data-testid="account-options-menu__account-details"]',
);
// get the public address for the "third account"
const recreatedThirdAccountAddress = await driver.findElement({
text: thirdAccount,
tag: 'div',
});
assert.strictEqual(
await recreatedThirdAccountAddress.getText(),
thirdAccountPublicAddress,
await driver.clickElement(accountTwoSelector);
const restoredSecondAccountPublicAddress = await checkAccountDetails(
driver,
);
assert.equal(restoredSecondAccountPublicAddress, secondAccount);
},
);
});
@ -264,3 +209,19 @@ describe('Add account', function () {
);
});
});
async function checkAccountDetails(driver) {
await driver.clickElement('[data-testid="account-options-menu-button"]');
await driver.clickElement(
'[data-testid="account-options-menu__account-details"]',
);
await driver.findVisibleElement('.account-details-modal');
// get the public address for the "second account"
const accountDOM = await driver.findElement('.qr-code__address');
const accountAddress = await accountDOM.getText();
await driver.clickElement('.account-modal__close');
await driver.waitForElementNotPresent('.account-details-modal ');
return accountAddress;
}

View File

@ -57,7 +57,7 @@ describe('Hide token', function () {
let assets = await driver.findElements('.asset-list-item');
assert.equal(assets.length, 2);
await driver.clickElement({ text: 'Assets', tag: 'button' });
await driver.clickElement({ text: 'Tokens', tag: 'button' });
await driver.clickElement({ text: 'TST', tag: 'span' });

View File

@ -44,7 +44,7 @@ describe('Create token, approve token and approve token without gas', function (
// imports custom token from extension
await driver.switchToWindow(extension);
await driver.clickElement(`[data-testid="home__asset-tab"]`);
await driver.clickElement({ tag: 'button', text: 'Assets' });
await driver.clickElement({ tag: 'button', text: 'Tokens' });
await driver.clickElement({ text: 'import tokens', tag: 'a' });
await driver.clickElement({
@ -68,7 +68,7 @@ describe('Create token, approve token and approve token without gas', function (
// renders balance for newly created token
await driver.clickElement('.app-header__logo-container');
await driver.clickElement({ tag: 'button', text: 'Assets' });
await driver.clickElement({ tag: 'button', text: 'Tokens' });
const asset = await driver.waitForSelector({
css: '.asset-list-item__token-value',
text: '10',

View File

@ -1,28 +1,29 @@
const { strict: assert } = require('assert');
const path = require('path');
const {
TEST_SEED_PHRASE,
convertToHexValue,
withFixtures,
regularDelayMs,
largeDelayMs,
completeImportSRPOnboardingFlow,
completeImportSRPOnboardingFlowWordByWord,
findAnotherAccountFromAccountList,
} = require('../helpers');
const FixtureBuilder = require('../fixture-builder');
const ganacheOptions = {
accounts: [
{
secretKey:
'0x53CB0AB5226EEBF4D872113D98332C1555DC304443BEE1CF759D15798D3C55A9',
balance: convertToHexValue(25000000000000000000),
},
],
};
describe('MetaMask Import UI', function () {
it('Importing wallet using Secret Recovery Phrase', async function () {
const ganacheOptions = {
accounts: [
{
secretKey:
'0x53CB0AB5226EEBF4D872113D98332C1555DC304443BEE1CF759D15798D3C55A9',
balance: convertToHexValue(25000000000000000000),
},
],
};
const testSeedPhrase =
'forum vessel pink push lonely enact gentle tail admit parrot grunt dress';
const testPassword = 'correct horse battery staple';
const testAddress = '0x0Cc5261AB8cE458dc977078A3623E2BaDD27afD3';
@ -38,7 +39,7 @@ describe('MetaMask Import UI', function () {
await completeImportSRPOnboardingFlow(
driver,
testSeedPhrase,
TEST_SEED_PHRASE,
testPassword,
);
@ -130,17 +131,6 @@ describe('MetaMask Import UI', function () {
});
it('Importing wallet using Secret Recovery Phrase with pasting word by word', async function () {
const ganacheOptions = {
accounts: [
{
secretKey:
'0x53CB0AB5226EEBF4D872113D98332C1555DC304443BEE1CF759D15798D3C55A9',
balance: convertToHexValue(25000000000000000000),
},
],
};
const testSeedPhrase =
'forum vessel pink push lonely enact gentle tail admit parrot grunt dress';
const testPassword = 'correct horse battery staple';
const testAddress = '0x0Cc5261AB8cE458dc977078A3623E2BaDD27afD3';
@ -156,7 +146,7 @@ describe('MetaMask Import UI', function () {
await completeImportSRPOnboardingFlowWordByWord(
driver,
testSeedPhrase,
TEST_SEED_PHRASE,
testPassword,
);
@ -177,15 +167,6 @@ describe('MetaMask Import UI', function () {
});
it('Import Account using private key', async function () {
const ganacheOptions = {
accounts: [
{
secretKey:
'0x53CB0AB5226EEBF4D872113D98332C1555DC304443BEE1CF759D15798D3C55A9',
balance: convertToHexValue(25000000000000000000),
},
],
};
const testPrivateKey1 =
'14abe6f4aab7f9f626fe981c864d0adeb5685f289ac9270c27b8fd790b4235d6';
const testPrivateKey2 =
@ -221,13 +202,12 @@ describe('MetaMask Import UI', function () {
assert.equal(await importedAccountName.getText(), 'Account 4');
// should show the imported label
await driver.clickElement('.account-menu__icon');
// confirm 4th account is account 4, as expected
const accountMenuItemSelector = '.account-menu__account:nth-child(4)';
const fourthAccountName = await driver.findElement(
`${accountMenuItemSelector} .account-menu__name`,
const accountMenuItemSelector = await findAnotherAccountFromAccountList(
driver,
4,
'Account 4',
);
assert.equal(await fourthAccountName.getText(), 'Account 4');
// confirm label is present on the same menu item
const importedLabel = await driver.findElement(
`${accountMenuItemSelector} .keyring-label`,
@ -284,16 +264,6 @@ describe('MetaMask Import UI', function () {
});
it('Import Account using json file', async function () {
const ganacheOptions = {
accounts: [
{
secretKey:
'0x53CB0AB5226EEBF4D872113D98332C1555DC304443BEE1CF759D15798D3C55A9',
balance: convertToHexValue(25000000000000000000),
},
],
};
await withFixtures(
{
fixtures: new FixtureBuilder()
@ -336,13 +306,13 @@ describe('MetaMask Import UI', function () {
assert.equal(await importedAccountName.getText(), 'Account 4');
// should show the imported label
await driver.clickElement('.account-menu__icon');
// confirm 4th account is account 4, as expected
const accountMenuItemSelector = '.account-menu__account:nth-child(4)';
const fourthAccountName = await driver.findElement(
`${accountMenuItemSelector} .account-menu__name`,
const accountMenuItemSelector = await findAnotherAccountFromAccountList(
driver,
4,
'Account 4',
);
assert.equal(await fourthAccountName.getText(), 'Account 4');
// confirm label is present on the same menu item
const importedLabel = await driver.findElement(
`${accountMenuItemSelector} .keyring-label`,
@ -360,15 +330,6 @@ describe('MetaMask Import UI', function () {
it('Import Account using private key of an already active account should result in an error', async function () {
const testPrivateKey =
'0x53CB0AB5226EEBF4D872113D98332C1555DC304443BEE1CF759D15798D3C55A9';
const ganacheOptions = {
accounts: [
{
secretKey: testPrivateKey,
balance: convertToHexValue(25000000000000000000),
},
],
};
await withFixtures(
{
fixtures: new FixtureBuilder()
@ -400,44 +361,36 @@ describe('MetaMask Import UI', function () {
);
});
it('Connects to a Hardware wallet', async function () {
const ganacheOptions = {
accounts: [
if (process.env.ENABLE_MV3) {
it('Connects to a Hardware wallet for trezor', async function () {
await withFixtures(
{
secretKey:
'0x53CB0AB5226EEBF4D872113D98332C1555DC304443BEE1CF759D15798D3C55A9',
balance: convertToHexValue(25000000000000000000),
fixtures: new FixtureBuilder().build(),
ganacheOptions,
title: this.test.title,
},
],
};
async ({ driver }) => {
await driver.navigate();
await driver.fill('#password', 'correct horse battery staple');
await driver.press('#password', driver.Key.ENTER);
await withFixtures(
{
fixtures: new FixtureBuilder().build(),
ganacheOptions,
title: this.test.title,
},
async ({ driver }) => {
await driver.navigate();
await driver.fill('#password', 'correct horse battery staple');
await driver.press('#password', driver.Key.ENTER);
// choose Connect hardware wallet from the account menu
await driver.clickElement('.account-menu__icon');
await driver.clickElement({
text: 'Connect hardware wallet',
tag: 'div',
});
await driver.delay(regularDelayMs);
// choose Connect hardware wallet from the account menu
await driver.clickElement('.account-menu__icon');
await driver.clickElement({
text: 'Connect hardware wallet',
tag: 'div',
});
await driver.delay(regularDelayMs);
// should open the TREZOR Connect popup
await driver.clickElement('.hw-connect__btn:nth-of-type(2)');
await driver.delay(largeDelayMs * 2);
await driver.clickElement({ text: 'Continue', tag: 'button' });
await driver.waitUntilXWindowHandles(2);
const allWindows = await driver.getAllWindowHandles();
assert.equal(allWindows.length, 2);
},
);
});
// should open the TREZOR Connect popup
await driver.clickElement('.hw-connect__btn:nth-of-type(2)');
await driver.delay(largeDelayMs * 2);
await driver.clickElement({ text: 'Continue', tag: 'button' });
await driver.waitUntilXWindowHandles(2);
const allWindows = await driver.getAllWindowHandles();
assert.equal(allWindows.length, 2);
},
);
});
}
});

View File

@ -1,5 +1,9 @@
const { strict: assert } = require('assert');
const { convertToHexValue, withFixtures } = require('../helpers');
const {
TEST_SEED_PHRASE_TWO,
convertToHexValue,
withFixtures,
} = require('../helpers');
const FixtureBuilder = require('../fixture-builder');
describe('MetaMask Responsive UI', function () {
@ -76,8 +80,6 @@ describe('MetaMask Responsive UI', function () {
it('Importing existing wallet from lock page', async function () {
const driverOptions = { openDevToolsForTabs: true };
const testSeedPhrase =
'phrase upgrade clock rough situate wedding elder clever doctor stamp excess tent';
await withFixtures(
{
@ -98,7 +100,7 @@ describe('MetaMask Responsive UI', function () {
await driver.pasteIntoField(
'[data-testid="import-srp__srp-word-0"]',
testSeedPhrase,
TEST_SEED_PHRASE_TWO,
);
await driver.fill('#password', 'correct horse battery staple');

View File

@ -1,6 +1,7 @@
const { strict: assert } = require('assert');
const { By } = require('selenium-webdriver');
const {
TEST_SEED_PHRASE,
convertToHexValue,
withFixtures,
completeCreateNewWalletOnboardingFlow,
@ -12,8 +13,6 @@ const {
const FixtureBuilder = require('../fixture-builder');
describe('MetaMask onboarding', function () {
const testSeedPhrase =
'forum vessel pink push lonely enact gentle tail admit parrot grunt dress';
const testPassword = 'correct horse battery staple';
const wrongSeedPhrase =
'test test test test test test test test test test test test';
@ -63,7 +62,7 @@ describe('MetaMask onboarding', function () {
await completeImportSRPOnboardingFlow(
driver,
testSeedPhrase,
TEST_SEED_PHRASE,
testPassword,
);
@ -164,7 +163,7 @@ describe('MetaMask onboarding', function () {
// Check that the error message is displayed for the password fields
await driver.isElementPresent(
// eslint-disable-next-line prettier/prettier
{ text: 'Passwords don\'t match', tag: 'h6' },
{ text: "Passwords don't match", tag: 'h6' },
true,
);
@ -188,7 +187,7 @@ describe('MetaMask onboarding', function () {
async ({ driver }) => {
await driver.navigate();
await importSRPOnboardingFlow(driver, testSeedPhrase, testPassword);
await importSRPOnboardingFlow(driver, TEST_SEED_PHRASE, testPassword);
// Verify site
assert.equal(
await driver.isElementPresent({
@ -267,7 +266,7 @@ describe('MetaMask onboarding', function () {
async ({ driver, secondaryGanacheServer }) => {
await driver.navigate();
await importSRPOnboardingFlow(driver, testSeedPhrase, testPassword);
await importSRPOnboardingFlow(driver, TEST_SEED_PHRASE, testPassword);
// Add custome network localhost 8546 during onboarding
await driver.clickElement({ text: 'Advanced configuration', tag: 'a' });

View File

@ -1,88 +1,14 @@
const { strict: assert } = require('assert');
const { convertToHexValue, withFixtures, openDapp } = require('../helpers');
const {
convertToHexValue,
withFixtures,
openDapp,
setupPhishingDetectionMocks,
mockPhishingDetection,
} = require('../helpers');
const FixtureBuilder = require('../fixture-builder');
const STALELIST_URL =
'https://static.metafi.codefi.network/api/v1/lists/stalelist.json';
const emptyHtmlPage = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>title</title>
</head>
<body>
Empty page
</body>
</html>`;
/**
* Setup fetch mocks for the phishing detection feature.
*
* The mock configuration will show that "127.0.0.1" is blocked. The dynamic lookup on the warning
* page can be customized, so that we can test both the MetaMask and PhishFort block cases.
*
* @param {import('mockttp').Mockttp} mockServer - The mock server.
* @param {object} metamaskPhishingConfigResponse - The response for the dynamic phishing
* configuration lookup performed by the warning page.
*/
async function setupPhishingDetectionMocks(
mockServer,
metamaskPhishingConfigResponse,
) {
await mockServer.forGet(STALELIST_URL).thenCallback(() => {
return {
statusCode: 200,
json: {
version: 2,
tolerance: 2,
fuzzylist: [],
allowlist: [],
blocklist: ['127.0.0.1'],
lastUpdated: 0,
},
};
});
await mockServer
.forGet('https://github.com/MetaMask/eth-phishing-detect/issues/new')
.thenCallback(() => {
return {
statusCode: 200,
body: emptyHtmlPage,
};
});
await mockServer
.forGet('https://github.com/phishfort/phishfort-lists/issues/new')
.thenCallback(() => {
return {
statusCode: 200,
body: emptyHtmlPage,
};
});
await mockServer
.forGet(
'https://raw.githubusercontent.com/MetaMask/eth-phishing-detect/master/src/config.json',
)
.thenCallback(() => metamaskPhishingConfigResponse);
}
describe('Phishing Detection', function () {
function mockPhishingDetection(mockServer) {
setupPhishingDetectionMocks(mockServer, {
statusCode: 200,
json: {
version: 2,
tolerance: 2,
fuzzylist: [],
whitelist: [],
blacklist: ['127.0.0.1'],
lastUpdated: 0,
},
});
}
const ganacheOptions = {
accounts: [
{

View File

@ -1,4 +1,8 @@
const { convertToHexValue, withFixtures } = require('../helpers');
const {
convertToHexValue,
withFixtures,
sendTransaction,
} = require('../helpers');
const FixtureBuilder = require('../fixture-builder');
describe('Simple send', function () {
@ -22,16 +26,11 @@ describe('Simple send', function () {
await driver.navigate();
await driver.fill('#password', 'correct horse battery staple');
await driver.press('#password', driver.Key.ENTER);
await driver.clickElement('[data-testid="eth-overview-send"]');
await driver.fill(
'[data-testid="ens-input"]',
await sendTransaction(
driver,
'0x985c30949c92df7a0bd42e0f3e3d539ece98db24',
'1',
);
await driver.fill('.unit-input__input', '1');
await driver.clickElement('[data-testid="page-container-footer-next"]');
await driver.clickElement('[data-testid="page-container-footer-next"]');
await driver.clickElement('[data-testid="home__activity-tab"]');
await driver.findElement('.transaction-list-item');
},
);
});

View File

@ -403,6 +403,10 @@ class Driver {
throw new Error(`No window with title: ${title}`);
}
async closeWindow() {
await this.driver.close();
}
// Close Alert Popup
async closeAlertPopup() {
return await this.driver.switchTo().alert().accept();

View File

@ -1,2 +1,4 @@
process.env.METAMASK_ENVIRONMENT = 'test';
process.env.SUPPORT_LINK = 'https://support.metamask.io';
process.env.IFRAME_EXECUTION_ENVIRONMENT_URL =
'https://execution.metamask.io/0.16.0-flask.1/index.html';

View File

@ -1,9 +0,0 @@
// jest specific env vars that break mocha tests
import { generateIconNames } from '../../development/generate-icon-names';
/**
* Used for testing components that use the Icon component
* 'ui/components/component-library/icon/icon.js'
*/
process.env.ICON_NAMES = generateIconNames();

View File

@ -79,6 +79,7 @@ exports[`AccountListItem Component render should match snapshot 1`] = `
>
<div
class="account-mismatch-warning__tooltip-container-icon"
data-testid="account-mismatch-warning-tooltip"
>
<svg
class="info-icon info-icon--warning"

View File

@ -5,11 +5,6 @@ import { renderWithProvider } from '../../../../test/lib/render-helpers';
import mockState from '../../../../test/data/mock-state.json';
import AccountListItem from './account-list-item';
jest.mock('../../../../shared/modules/hexstring-utils', () => ({
...jest.requireActual('../../../../shared/modules/hexstring-utils'),
toChecksumHexAddress: jest.fn(() => 'mockCheckSumAddress'),
}));
describe('AccountListItem Component', () => {
const store = configureStore()(mockState);
@ -93,7 +88,7 @@ describe('AccountListItem Component', () => {
<AccountListItem {...props} />,
store,
);
expect(queryByText('mockCheckSumAddress')).not.toBeInTheDocument();
expect(queryByText('0xmockAddress')).not.toBeInTheDocument();
const displayAddressProps = {
...props,
@ -101,7 +96,23 @@ describe('AccountListItem Component', () => {
};
rerender(<AccountListItem {...displayAddressProps} />);
expect(queryByText('mockCheckSumAddress')).toBeInTheDocument();
expect(queryByText('0xmockAddress')).toBeInTheDocument();
});
it('render without <AccountMismatchWarning /> if hideDefaultMismatchWarning is true', () => {
const { getByTestId, rerender } = renderWithProvider(
<AccountListItem {...props} />,
store,
);
const infoIcon = getByTestId('account-mismatch-warning-tooltip');
expect(infoIcon).toBeInTheDocument();
rerender(<AccountListItem {...props} hideDefaultMismatchWarning />);
expect(infoIcon).not.toBeInTheDocument();
});
});
});

View File

@ -10,9 +10,18 @@ export default function AccountListItem({
displayAddress = false,
handleClick,
icon = null,
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
hideDefaultMismatchWarning = false,
///: END:ONLY_INCLUDE_IN
}) {
const { name, address, balance } = account || {};
let showDefaultMismatchWarning = true;
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
showDefaultMismatchWarning = !hideDefaultMismatchWarning;
///: END:ONLY_INCLUDE_IN
return (
<div
className={`account-list-item ${className}`}
@ -34,9 +43,10 @@ export default function AccountListItem({
{icon}
</div>
) : null}
<AccountMismatchWarning address={address} />
{showDefaultMismatchWarning && (
<AccountMismatchWarning address={address} />
)}
</div>
{displayAddress && name && (
<div className="account-list-item__account-address">
{toChecksumHexAddress(address)}
@ -71,4 +81,10 @@ AccountListItem.propTypes = {
* Pass icon component to be displayed. Currently not used
*/
icon: PropTypes.node,
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
/**
* MMI Prop, will hide the default AccountMismatchWarning when needed
*/
hideDefaultMismatchWarning: PropTypes.bool,
///: END:ONLY_INCLUDE_IN
};

View File

@ -88,6 +88,41 @@ exports[`Account Menu Render Content should not render keyring label if keyring
>
Account 1
</div>
<label
class="box mm-text mm-label mm-label--html-for mm-text--body-md mm-text--font-weight-bold box--display-flex box--flex-direction-row box--align-items-center box--color-text-default"
for="address-0"
/>
<div
class="account-menu__balance-container"
>
<div
class="currency-display-component account-menu__balance"
data-testid="account-menu__balance"
title="0 ETH"
>
<span
class="currency-display-component__prefix"
/>
<span
class="currency-display-component__text"
>
0
</span>
<span
class="currency-display-component__suffix"
>
ETH
</span>
</div>
<span
class="account-menu__address"
>
·
0x00
</span>
</div>
<div
class="currency-display-component account-menu__balance"
data-testid="account-menu__balance"
@ -168,6 +203,41 @@ exports[`Account Menu Render Content should not render keyring label if keyring
>
Imported Account 1
</div>
<label
class="box mm-text mm-label mm-label--html-for mm-text--body-md mm-text--font-weight-bold box--display-flex box--flex-direction-row box--align-items-center box--color-text-default"
for="address-0"
/>
<div
class="account-menu__balance-container"
>
<div
class="currency-display-component account-menu__balance"
data-testid="account-menu__balance"
title="0 ETH"
>
<span
class="currency-display-component__prefix"
/>
<span
class="currency-display-component__text"
>
0
</span>
<span
class="currency-display-component__suffix"
>
ETH
</span>
</div>
<span
class="account-menu__address"
>
·
0x1
</span>
</div>
<div
class="currency-display-component account-menu__balance"
data-testid="account-menu__balance"
@ -245,6 +315,24 @@ exports[`Account Menu Render Content should not render keyring label if keyring
Connect hardware wallet
</div>
</button>
<button
class="account-menu__item account-menu__item--clickable"
>
<div
class="account-menu__item__text"
>
Connect Custodial Account
</div>
</button>
<button
class="account-menu__item account-menu__item--clickable"
>
<div
class="account-menu__item__text"
>
Compliance
</div>
</button>
<div
class="account-menu__divider"
/>

View File

@ -30,6 +30,10 @@ import {
///: BEGIN:ONLY_INCLUDE_IN(snaps)
NOTIFICATIONS_ROUTE,
///: END:ONLY_INCLUDE_IN
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
CUSTODY_ACCOUNT_ROUTE,
COMPLIANCE_FEATURE_ROUTE,
///: END:ONLY_INCLUDE_IN
} from '../../../helpers/constants/routes';
import TextField from '../../ui/text-field';
@ -38,6 +42,12 @@ import SearchIcon from '../../ui/icon/search-icon';
import { SUPPORT_LINK } from '../../../../shared/lib/ui-utils';
import { IconColor } from '../../../helpers/constants/design-system';
import { Icon, IconName, IconSize } from '../../component-library';
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
import { shortenAddress } from '../../../helpers/utils/util';
import CustodyLabels from '../../institutional/custody-labels';
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
///: END:ONLY_INCLUDE_IN
import KeyRingLabel from './keyring-label';
export function AccountMenuItem(props) {
@ -91,6 +101,11 @@ export default class AccountMenu extends Component {
///: BEGIN:ONLY_INCLUDE_IN(snaps)
unreadNotificationsCount: PropTypes.number,
///: END:ONLY_INCLUDE_IN
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
custodyAccountDetails: PropTypes.object,
mmiPortfolioEnabled: PropTypes.bool,
mmiPortfolioUrl: PropTypes.string,
///: END:ONLY_INCLUDE_IN
};
accountsRef;
@ -173,6 +188,9 @@ export default class AccountMenu extends Component {
setSelectedAccount,
addressConnectedSubjectMap,
originOfCurrentTab,
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
custodyAccountDetails,
///: END:ONLY_INCLUDE_IN
} = this.props;
const { searchQuery } = this.state;
@ -205,6 +223,13 @@ export default class AccountMenu extends Component {
addressConnectedSubjectMap[identity.address] || {};
const iconAndNameForOpenSubject = addressSubjects[originOfCurrentTab];
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
const labels = custodyAccountDetails
? custodyAccountDetails[toChecksumHexAddress(identity.address)]
?.labels || []
: [];
///: END:ONLY_INCLUDE_IN
return (
<button
className="account-menu__account account-menu__item--clickable"
@ -233,12 +258,41 @@ export default class AccountMenu extends Component {
<Identicon address={identity.address} diameter={24} />
<div className="account-menu__account-info">
<div className="account-menu__name">{identity.name || ''}</div>
<UserPreferencedCurrencyDisplay
className="account-menu__balance"
data-testid="account-menu__balance"
value={identity.balance}
type={PRIMARY}
/>
{
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
<>
{labels && (
<CustodyLabels
labels={labels}
background="transparent"
hideNetwork
/>
)}
<div className="account-menu__balance-container">
<UserPreferencedCurrencyDisplay
className="account-menu__balance"
data-testid="account-menu__balance"
value={identity.balance}
type={PRIMARY}
/>{' '}
<span className="account-menu__address">
{' '}
· {shortenAddress(identity.address)}
</span>
</div>
</>
///: END:ONLY_INCLUDE_IN
}
{
///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask)
<UserPreferencedCurrencyDisplay
className="account-menu__balance"
data-testid="account-menu__balance"
value={identity.balance}
type={PRIMARY}
/>
///: END:ONLY_INCLUDE_IN
}
</div>
<KeyRingLabel keyring={keyring} />
{iconAndNameForOpenSubject ? (
@ -313,6 +367,10 @@ export default class AccountMenu extends Component {
///: BEGIN:ONLY_INCLUDE_IN(snaps)
unreadNotificationsCount,
///: END:ONLY_INCLUDE_IN
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
mmiPortfolioEnabled,
mmiPortfolioUrl,
///: END:ONLY_INCLUDE_IN
} = this.props;
if (!isAccountMenuOpen) {
@ -413,6 +471,76 @@ export default class AccountMenu extends Component {
}
text={t('connectHardwareWallet')}
/>
{
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
<>
<AccountMenuItem
onClick={() => {
toggleAccountMenu();
trackEvent({
category: MetaMetricsEventCategory.Navigation,
event:
MetaMetricsEventName.UserClickedConnectCustodialAccount,
});
if (getEnvironmentType() === ENVIRONMENT_TYPE_POPUP) {
global.platform.openExtensionInBrowser(CUSTODY_ACCOUNT_ROUTE);
} else {
history.push(CUSTODY_ACCOUNT_ROUTE);
}
}}
Icon={
<Icon
name={IconName.Custody}
color={IconColor.primaryDefault}
/>
}
text={t('connectCustodialAccountMenu')}
/>
{mmiPortfolioEnabled && (
<AccountMenuItem
onClick={() => {
toggleAccountMenu();
trackEvent({
category: MetaMetricsEventCategory.Navigation,
event: MetaMetricsEventName.UserClickedPortfolioButton,
});
window.open(mmiPortfolioUrl, '_blank');
}}
Icon={
<Icon
name={IconName.MmmiPortfolioDashboard}
color={IconColor.primaryDefault}
/>
}
text={t('portfolioDashboard')}
/>
)}
<AccountMenuItem
onClick={() => {
toggleAccountMenu();
trackEvent({
category: MetaMetricsEventCategory.Navigation,
event: MetaMetricsEventName.UserClickedCompliance,
});
if (getEnvironmentType() === ENVIRONMENT_TYPE_POPUP) {
global.platform.openExtensionInBrowser(
COMPLIANCE_FEATURE_ROUTE,
);
} else {
history.push(COMPLIANCE_FEATURE_ROUTE);
}
}}
Icon={
<Icon
name={IconName.Compliance}
color={IconColor.primaryDefault}
/>
}
text={t('compliance')}
/>
</>
///: END:ONLY_INCLUDE_IN
}
<div className="account-menu__divider" />
{
///: BEGIN:ONLY_INCLUDE_IN(snaps)

View File

@ -1,6 +1,13 @@
import { connect } from 'react-redux';
import { compose } from 'redux';
import { withRouter } from 'react-router-dom';
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
import {
getMmiPortfolioEnabled,
getMmiPortfolioUrl,
getCustodyAccountDetails,
} from '../../../selectors/institutional/selectors';
///: END:ONLY_INCLUDE_IN
import {
toggleAccountMenu,
setSelectedAccount,
@ -45,6 +52,11 @@ function mapStateToProps(state) {
///: BEGIN:ONLY_INCLUDE_IN(snaps)
unreadNotificationsCount,
///: END:ONLY_INCLUDE_IN
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
mmiPortfolioUrl: getMmiPortfolioUrl(state),
mmiPortfolioEnabled: getMmiPortfolioEnabled(state),
custodyAccountDetails: getCustodyAccountDetails(state),
///: END:ONLY_INCLUDE_IN
};
}

View File

@ -74,7 +74,7 @@ describe('Account Menu', () => {
it('renders user preference currency display balance from account balance', () => {
const accountBalance = screen.queryAllByTestId('account-menu__balance');
expect(accountBalance).toHaveLength(2);
expect(accountBalance).toHaveLength(4);
});
it('simulate click', () => {

View File

@ -1,6 +1,7 @@
import React, { useContext, useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useHistory } from 'react-router-dom';
import { ApprovalType } from '@metamask/controller-utils';
import { I18nContext } from '../../../contexts/i18n';
import Box from '../../ui/box';
import {
@ -26,7 +27,6 @@ import {
import {
ENVIRONMENT_TYPE_FULLSCREEN,
ENVIRONMENT_TYPE_POPUP,
MESSAGE_TYPE,
ORIGIN_METAMASK,
} from '../../../../shared/constants/app';
import { requestUserApproval } from '../../../store/actions';
@ -66,7 +66,7 @@ const AddNetwork = () => {
unapprovedConfirmations?.find((confirmation) => {
return (
confirmation.origin === 'metamask' &&
confirmation.type === MESSAGE_TYPE.ADD_ETHEREUM_CHAIN
confirmation.type === ApprovalType.AddEthereumChain
);
});
if (!showPopover && anAddNetworkConfirmationFromMetaMaskExists) {
@ -258,7 +258,7 @@ const AddNetwork = () => {
await dispatch(
requestUserApproval({
origin: ORIGIN_METAMASK,
type: MESSAGE_TYPE.ADD_ETHEREUM_CHAIN,
type: ApprovalType.AddEthereumChain,
requestData: {
chainId: item.chainId,
rpcUrl: item.rpcUrl,

Some files were not shown because too many files have changed in this diff Show More