mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 01:47:00 +01:00
Add desktop support (#17683)
Use DesktopManager in background script to redirect internal and external connections to the desktop app. Include DesktopController in the MetaMask controller. Support desktop keyrings in MetaMask controller via the overrides object. Create middleware handler to connect to the desktop app while UI code is pending. Add build system support for desktop specific configuration variables.
This commit is contained in:
parent
0af56b1b1e
commit
cc99a25228
@ -54,6 +54,16 @@ import setupEnsIpfsResolver from './lib/ens-ipfs/setup';
|
||||
import { deferredPromise, getPlatform } from './lib/util';
|
||||
/* eslint-enable import/first */
|
||||
|
||||
/* eslint-disable import/order */
|
||||
///: BEGIN:ONLY_INCLUDE_IN(desktop)
|
||||
import {
|
||||
CONNECTION_TYPE_EXTERNAL,
|
||||
CONNECTION_TYPE_INTERNAL,
|
||||
} from '@metamask/desktop/dist/constants';
|
||||
import DesktopManager from '@metamask/desktop/dist/desktop-manager';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
/* eslint-enable import/order */
|
||||
|
||||
const { sentry } = global;
|
||||
const firstTimeState = { ...rawFirstTimeState };
|
||||
|
||||
@ -97,6 +107,13 @@ const PHISHING_WARNING_PAGE_TIMEOUT = ONE_SECOND_IN_MILLISECONDS;
|
||||
const ACK_KEEP_ALIVE_MESSAGE = 'ACK_KEEP_ALIVE_MESSAGE';
|
||||
const WORKER_KEEP_ALIVE_MESSAGE = 'WORKER_KEEP_ALIVE_MESSAGE';
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(desktop)
|
||||
const OVERRIDE_ORIGIN = {
|
||||
EXTENSION: 'EXTENSION',
|
||||
DESKTOP: 'DESKTOP_APP',
|
||||
};
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
// Event emitter for state persistence
|
||||
export const statePersistenceEvents = new EventEmitter();
|
||||
|
||||
@ -245,6 +262,11 @@ async function initialize() {
|
||||
try {
|
||||
const initState = await loadStateFromPersistence();
|
||||
const initLangCode = await getFirstPreferredLangCode();
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(desktop)
|
||||
await DesktopManager.init(platform.getVersion());
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
setupController(initState, initLangCode);
|
||||
if (!isManifestV3) {
|
||||
await loadPhishingWarningPage();
|
||||
@ -482,6 +504,26 @@ export function setupController(initState, initLangCode, overrides) {
|
||||
* @param {Port} remotePort - The port provided by a new context.
|
||||
*/
|
||||
connectRemote = async (remotePort) => {
|
||||
///: BEGIN:ONLY_INCLUDE_IN(desktop)
|
||||
if (
|
||||
DesktopManager.isDesktopEnabled() &&
|
||||
OVERRIDE_ORIGIN.DESKTOP !== overrides?.getOrigin?.()
|
||||
) {
|
||||
DesktopManager.createStream(remotePort, CONNECTION_TYPE_INTERNAL).then(
|
||||
() => {
|
||||
// When in Desktop Mode the responsibility to send CONNECTION_READY is on the desktop app side
|
||||
if (isManifestV3) {
|
||||
// Message below if captured by UI code in app/scripts/ui.js which will trigger UI initialisation
|
||||
// This ensures that UI is initialised only after background is ready
|
||||
// It fixes the issue of blank screen coming when extension is loaded, the issue is very frequent in MV3
|
||||
remotePort.postMessage({ name: 'CONNECTION_READY' });
|
||||
}
|
||||
},
|
||||
);
|
||||
return;
|
||||
}
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
const processName = remotePort.name;
|
||||
|
||||
if (metamaskBlockedPorts.includes(remotePort.name)) {
|
||||
@ -584,6 +626,16 @@ export function setupController(initState, initLangCode, overrides) {
|
||||
|
||||
// communication with page or other extension
|
||||
connectExternal = (remotePort) => {
|
||||
///: BEGIN:ONLY_INCLUDE_IN(desktop)
|
||||
if (
|
||||
DesktopManager.isDesktopEnabled() &&
|
||||
OVERRIDE_ORIGIN.DESKTOP !== overrides?.getOrigin?.()
|
||||
) {
|
||||
DesktopManager.createStream(remotePort, CONNECTION_TYPE_EXTERNAL);
|
||||
return;
|
||||
}
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
const portStream =
|
||||
overrides?.getPortStream?.(remotePort) || new PortStream(remotePort);
|
||||
controller.setupUntrustedCommunication({
|
||||
@ -762,6 +814,14 @@ export function setupController(initState, initLangCode, overrides) {
|
||||
|
||||
updateBadge();
|
||||
}
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(desktop)
|
||||
if (OVERRIDE_ORIGIN.DESKTOP !== overrides?.getOrigin?.()) {
|
||||
controller.store.subscribe((state) => {
|
||||
DesktopManager.setState(state);
|
||||
});
|
||||
}
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -0,0 +1,43 @@
|
||||
import { MESSAGE_TYPE } from '../../../../../../shared/constants/app';
|
||||
|
||||
/**
|
||||
* A wrapper for `eth_accounts` that returns an empty array when permission is denied.
|
||||
*/
|
||||
|
||||
const requestEthereumAccounts = {
|
||||
methodNames: [MESSAGE_TYPE.ENABLE_DESKTOP],
|
||||
implementation: enableDesktop,
|
||||
hookNames: {
|
||||
testDesktopConnection: true,
|
||||
generateOtp: true,
|
||||
},
|
||||
};
|
||||
export default requestEthereumAccounts;
|
||||
|
||||
/**
|
||||
* @typedef {Record<string, Function>} EthAccountsOptions
|
||||
* @property {Function} getAccounts - Gets the accounts for the requesting
|
||||
* origin.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {import('json-rpc-engine').JsonRpcRequest<unknown>} _req - The JSON-RPC request object.
|
||||
* @param {import('json-rpc-engine').JsonRpcResponse<true>} res - The JSON-RPC response object.
|
||||
* @param {Function} _next - The json-rpc-engine 'next' callback.
|
||||
* @param {Function} end - The json-rpc-engine 'end' callback.
|
||||
* @param {EthAccountsOptions} options - The RPC method hooks.
|
||||
*/
|
||||
async function enableDesktop(
|
||||
_req,
|
||||
res,
|
||||
_next,
|
||||
end,
|
||||
{ testDesktopConnection, generateOtp },
|
||||
) {
|
||||
const testResult = await testDesktopConnection();
|
||||
const otp = testResult.isConnected ? await generateOtp() : undefined;
|
||||
|
||||
res.result = { ...testResult, otp };
|
||||
return end();
|
||||
}
|
@ -7,6 +7,10 @@ import sendMetadata from './send-metadata';
|
||||
import switchEthereumChain from './switch-ethereum-chain';
|
||||
import watchAsset from './watch-asset';
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(desktop)
|
||||
import enableDesktop from './desktop/enable-desktop';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
const handlers = [
|
||||
addEthereumChain,
|
||||
ethAccounts,
|
||||
@ -16,5 +20,8 @@ const handlers = [
|
||||
sendMetadata,
|
||||
switchEthereumChain,
|
||||
watchAsset,
|
||||
///: BEGIN:ONLY_INCLUDE_IN(desktop)
|
||||
enableDesktop,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
];
|
||||
export default handlers;
|
||||
|
@ -41,6 +41,7 @@ export const SENTRY_STATE = {
|
||||
currentLocale: true,
|
||||
customNonceValue: true,
|
||||
defaultHomeActiveTabName: true,
|
||||
desktopEnabled: true,
|
||||
featureFlags: true,
|
||||
firstTimeFlowType: true,
|
||||
forgottenPassword: true,
|
||||
@ -140,23 +141,7 @@ export default function setupSentry({ release, getState }) {
|
||||
],
|
||||
release,
|
||||
beforeSend: (report) => rewriteReport(report, getState),
|
||||
beforeBreadcrumb(breadcrumb) {
|
||||
if (getState) {
|
||||
const appState = getState();
|
||||
if (
|
||||
Object.values(appState).length &&
|
||||
(!appState?.store?.metamask?.participateInMetaMetrics ||
|
||||
!appState?.store?.metamask?.completedOnboarding ||
|
||||
breadcrumb?.category === 'ui.input')
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
const newBreadcrumb = removeUrlsFromBreadCrumb(breadcrumb);
|
||||
return newBreadcrumb;
|
||||
},
|
||||
beforeBreadcrumb: beforeBreadcrumb(getState),
|
||||
});
|
||||
|
||||
return Sentry;
|
||||
@ -178,6 +163,32 @@ function hideUrlIfNotInternal(url) {
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a method that handles the Sentry breadcrumb using a specific method to get the extension state
|
||||
*
|
||||
* @param {Function} getState - A method that returns the state of the extension
|
||||
* @returns {(breadcrumb: object) => object} A method that modifies a Sentry breadcrumb object
|
||||
*/
|
||||
export function beforeBreadcrumb(getState) {
|
||||
return (breadcrumb) => {
|
||||
if (getState) {
|
||||
const appState = getState();
|
||||
if (
|
||||
Object.values(appState).length &&
|
||||
(!appState?.store?.metamask?.participateInMetaMetrics ||
|
||||
!appState?.store?.metamask?.completedOnboarding ||
|
||||
breadcrumb?.category === 'ui.input')
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
const newBreadcrumb = removeUrlsFromBreadCrumb(breadcrumb);
|
||||
return newBreadcrumb;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives a Sentry breadcrumb object and potentially removes urls
|
||||
* from its `data` property, it particular those possibly found at
|
||||
@ -315,8 +326,11 @@ function rewriteErrorMessages(report, rewriteFn) {
|
||||
}
|
||||
|
||||
function rewriteReportUrls(report) {
|
||||
// update request url
|
||||
report.request.url = toMetamaskUrl(report.request.url);
|
||||
if (report.request?.url) {
|
||||
// update request url
|
||||
report.request.url = toMetamaskUrl(report.request.url);
|
||||
}
|
||||
|
||||
// update exception stack trace
|
||||
if (report.exception && report.exception.values) {
|
||||
report.exception.values.forEach((item) => {
|
||||
@ -330,6 +344,10 @@ function rewriteReportUrls(report) {
|
||||
}
|
||||
|
||||
function toMetamaskUrl(origUrl) {
|
||||
if (!globalThis.location?.origin) {
|
||||
return origUrl;
|
||||
}
|
||||
|
||||
const filePath = origUrl?.split(globalThis.location.origin)[1];
|
||||
if (!filePath) {
|
||||
return origUrl;
|
||||
|
@ -176,6 +176,16 @@ import {
|
||||
import createRPCMethodTrackingMiddleware from './lib/createRPCMethodTrackingMiddleware';
|
||||
import { securityProviderCheck } from './lib/security-provider-helpers';
|
||||
|
||||
/* eslint-disable import/first */
|
||||
/* eslint-disable import/order */
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(desktop)
|
||||
import { DesktopController } from '@metamask/desktop/dist/controllers/desktop';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
/* eslint-enable import/first */
|
||||
/* eslint-enable import/order */
|
||||
|
||||
export const METAMASK_CONTROLLER_EVENTS = {
|
||||
// Fired after state changes that impact the extension badge (unapproved msg count)
|
||||
// The process of updating the badge happens in app/scripts/background.js.
|
||||
@ -650,10 +660,12 @@ export default class MetamaskController extends EventEmitter {
|
||||
let additionalKeyrings = [keyringBuilderFactory(QRHardwareKeyring)];
|
||||
|
||||
if (this.canUseHardwareWallets()) {
|
||||
const keyringOverrides = this.opts.overrides?.keyrings;
|
||||
|
||||
const additionalKeyringTypes = [
|
||||
TrezorKeyring,
|
||||
LedgerBridgeKeyring,
|
||||
LatticeKeyring,
|
||||
keyringOverrides?.trezor || TrezorKeyring,
|
||||
keyringOverrides?.ledger || LedgerBridgeKeyring,
|
||||
keyringOverrides?.lattice || LatticeKeyring,
|
||||
QRHardwareKeyring,
|
||||
];
|
||||
additionalKeyrings = additionalKeyringTypes.map((keyringType) =>
|
||||
@ -743,7 +755,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
});
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
this.snapExecutionService = new IframeExecutionService({
|
||||
const snapExecutionServiceArgs = {
|
||||
iframeUrl: new URL(
|
||||
'https://metamask.github.io/iframe-execution-environment/0.12.0',
|
||||
),
|
||||
@ -751,7 +763,11 @@ export default class MetamaskController extends EventEmitter {
|
||||
name: 'ExecutionService',
|
||||
}),
|
||||
setupSnapProvider: this.setupSnapProvider.bind(this),
|
||||
});
|
||||
};
|
||||
this.snapExecutionService =
|
||||
this.opts.overrides?.createSnapExecutionService?.(
|
||||
snapExecutionServiceArgs,
|
||||
) || new IframeExecutionService(snapExecutionServiceArgs);
|
||||
|
||||
const snapControllerMessenger = this.controllerMessenger.getRestricted({
|
||||
name: 'SnapController',
|
||||
@ -852,6 +868,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
messenger: cronjobControllerMessenger,
|
||||
});
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
this.detectTokensController = new DetectTokensController({
|
||||
preferences: this.preferencesController,
|
||||
tokensController: this.tokensController,
|
||||
@ -1112,6 +1129,12 @@ export default class MetamaskController extends EventEmitter {
|
||||
initState.SmartTransactionsController,
|
||||
);
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(desktop)
|
||||
this.desktopController = new DesktopController({
|
||||
initState: initState.DesktopController,
|
||||
});
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
// ensure accountTracker updates balances after network change
|
||||
this.networkController.on(NETWORK_EVENTS.NETWORK_DID_CHANGE, () => {
|
||||
this.accountTracker._updateAccounts();
|
||||
@ -1219,6 +1242,9 @@ export default class MetamaskController extends EventEmitter {
|
||||
CronjobController: this.cronjobController,
|
||||
NotificationController: this.notificationController,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
///: BEGIN:ONLY_INCLUDE_IN(desktop)
|
||||
DesktopController: this.desktopController.store,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
...resetOnRestartStore,
|
||||
});
|
||||
|
||||
@ -1251,6 +1277,9 @@ export default class MetamaskController extends EventEmitter {
|
||||
CronjobController: this.cronjobController,
|
||||
NotificationController: this.notificationController,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
///: BEGIN:ONLY_INCLUDE_IN(desktop)
|
||||
DesktopController: this.desktopController.store,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
...resetOnRestartStore,
|
||||
},
|
||||
controllerMessenger: this.controllerMessenger,
|
||||
@ -2154,6 +2183,24 @@ export default class MetamaskController extends EventEmitter {
|
||||
assetsContractController.getBalancesInSingleCall.bind(
|
||||
assetsContractController,
|
||||
),
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(desktop)
|
||||
getDesktopEnabled: this.desktopController.getDesktopEnabled.bind(
|
||||
this.desktopController,
|
||||
),
|
||||
setDesktopEnabled: this.desktopController.setDesktopEnabled.bind(
|
||||
this.desktopController,
|
||||
),
|
||||
generateOtp: this.desktopController.generateOtp.bind(
|
||||
this.desktopController,
|
||||
),
|
||||
testDesktopConnection: this.desktopController.testDesktopConnection.bind(
|
||||
this.desktopController,
|
||||
),
|
||||
disableDesktop: this.desktopController.disableDesktop.bind(
|
||||
this.desktopController,
|
||||
),
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
};
|
||||
}
|
||||
|
||||
@ -2623,6 +2670,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
//
|
||||
|
||||
async getKeyringForDevice(deviceName, hdPath = null) {
|
||||
const keyringOverrides = this.opts.overrides?.keyrings;
|
||||
let keyringName = null;
|
||||
if (
|
||||
deviceName !== HardwareDeviceNames.QR &&
|
||||
@ -2632,16 +2680,17 @@ export default class MetamaskController extends EventEmitter {
|
||||
}
|
||||
switch (deviceName) {
|
||||
case HardwareDeviceNames.trezor:
|
||||
keyringName = TrezorKeyring.type;
|
||||
keyringName = keyringOverrides?.trezor?.type || TrezorKeyring.type;
|
||||
break;
|
||||
case HardwareDeviceNames.ledger:
|
||||
keyringName = LedgerBridgeKeyring.type;
|
||||
keyringName =
|
||||
keyringOverrides?.ledger?.type || LedgerBridgeKeyring.type;
|
||||
break;
|
||||
case HardwareDeviceNames.qr:
|
||||
keyringName = QRHardwareKeyring.type;
|
||||
break;
|
||||
case HardwareDeviceNames.lattice:
|
||||
keyringName = LatticeKeyring.type;
|
||||
keyringName = keyringOverrides?.lattice?.type || LatticeKeyring.type;
|
||||
break;
|
||||
default:
|
||||
throw new Error(
|
||||
@ -3999,6 +4048,11 @@ export default class MetamaskController extends EventEmitter {
|
||||
this.alertController.setWeb3ShimUsageRecorded.bind(
|
||||
this.alertController,
|
||||
),
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(desktop)
|
||||
testDesktopConnection: this.desktopController.testDesktopConnection,
|
||||
generateOtp: this.desktopController.generateOtp,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
}),
|
||||
);
|
||||
|
||||
|
@ -182,11 +182,12 @@ export default class ExtensionPlatform {
|
||||
this._showNotification(title, message);
|
||||
}
|
||||
|
||||
_showNotification(title, message, url) {
|
||||
async _showNotification(title, message, url) {
|
||||
const iconUrl = await browser.runtime.getURL('../../images/icon-64.png');
|
||||
browser.notifications.create(url, {
|
||||
type: 'basic',
|
||||
title,
|
||||
iconUrl: browser.runtime.getURL('../../images/icon-64.png'),
|
||||
iconUrl,
|
||||
message,
|
||||
});
|
||||
}
|
||||
|
@ -15,6 +15,11 @@ const configurationPropertyNames = [
|
||||
'SEGMENT_WRITE_KEY',
|
||||
'SENTRY_DSN_DEV',
|
||||
'SWAPS_USE_DEV_APIS',
|
||||
// Desktop
|
||||
'COMPATIBILITY_VERSION_EXTENSION',
|
||||
'DISABLE_WEB_SOCKET_ENCRYPTION',
|
||||
'METAMASK_DEBUG',
|
||||
'SKIP_OTP_PAIRING_FLOW',
|
||||
];
|
||||
|
||||
const productionConfigurationPropertyNames = [
|
||||
|
@ -1110,7 +1110,7 @@ async function getEnvironmentVariables({ buildTarget, buildType, version }) {
|
||||
environment,
|
||||
testing,
|
||||
}),
|
||||
METAMASK_DEBUG: devMode,
|
||||
METAMASK_DEBUG: devMode || config.METAMASK_DEBUG === '1',
|
||||
METAMASK_ENVIRONMENT: environment,
|
||||
METAMASK_VERSION: version,
|
||||
METAMASK_BUILD_TYPE: buildType,
|
||||
@ -1126,6 +1126,10 @@ async function getEnvironmentVariables({ buildTarget, buildType, version }) {
|
||||
SWAPS_USE_DEV_APIS: config.SWAPS_USE_DEV_APIS === '1',
|
||||
TOKEN_ALLOWANCE_IMPROVEMENTS: config.TOKEN_ALLOWANCE_IMPROVEMENTS === '1',
|
||||
TRANSACTION_SECURITY_PROVIDER: config.TRANSACTION_SECURITY_PROVIDER === '1',
|
||||
// Desktop
|
||||
COMPATIBILITY_VERSION_EXTENSION: config.COMPATIBILITY_VERSION_EXTENSION,
|
||||
DISABLE_WEB_SOCKET_ENCRYPTION: config.DISABLE_WEB_SOCKET_ENCRYPTION === '1',
|
||||
SKIP_OTP_PAIRING_FLOW: config.SKIP_OTP_PAIRING_FLOW === '1',
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -231,6 +231,7 @@
|
||||
"@metamask/contract-metadata": "^2.2.0",
|
||||
"@metamask/controller-utils": "^1.0.0",
|
||||
"@metamask/design-tokens": "^1.9.0",
|
||||
"@metamask/desktop": "^0.2.0",
|
||||
"@metamask/eth-json-rpc-infura": "^7.0.0",
|
||||
"@metamask/eth-keyring-controller": "^10.0.0",
|
||||
"@metamask/eth-ledger-bridge-keyring": "^0.13.0",
|
||||
|
@ -27,6 +27,7 @@ export const ENVIRONMENT_TYPE_BACKGROUND = 'background';
|
||||
*/
|
||||
export const BuildType = {
|
||||
beta: 'beta',
|
||||
desktop: 'desktop',
|
||||
flask: 'flask',
|
||||
main: 'main',
|
||||
} as const;
|
||||
@ -60,6 +61,9 @@ export const MESSAGE_TYPE = {
|
||||
SNAP_DIALOG_CONFIRMATION: `${RestrictedMethods.snap_dialog}:confirmation`,
|
||||
SNAP_DIALOG_PROMPT: `${RestrictedMethods.snap_dialog}:prompt`,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
///: BEGIN:ONLY_INCLUDE_IN(desktop)
|
||||
ENABLE_DESKTOP: `metamask_enableDesktop`,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
} as const;
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
|
@ -92,6 +92,7 @@ async function main() {
|
||||
}
|
||||
|
||||
const configFile = path.join(__dirname, '.mocharc.js');
|
||||
const extraArgs = process.env.E2E_ARGS?.split(' ') || [];
|
||||
|
||||
const dir = 'test/test-results/e2e';
|
||||
fs.mkdir(dir, { recursive: true });
|
||||
@ -104,6 +105,7 @@ async function main() {
|
||||
`--config=${configFile}`,
|
||||
`--timeout=${testTimeoutInMilliseconds}`,
|
||||
'--reporter=xunit',
|
||||
...extraArgs,
|
||||
e2eTestPath,
|
||||
exit,
|
||||
],
|
||||
|
59
yarn.lock
59
yarn.lock
@ -3666,6 +3666,24 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@metamask/desktop@npm:^0.2.0":
|
||||
version: 0.2.0
|
||||
resolution: "@metamask/desktop@npm:0.2.0"
|
||||
dependencies:
|
||||
"@metamask/obs-store": ^5.0.0
|
||||
eciesjs: ^0.3.15
|
||||
end-of-stream: ^1.4.4
|
||||
extension-port-stream: ^2.0.0
|
||||
loglevel: ^1.8.0
|
||||
obj-multiplex: ^1.0.0
|
||||
otpauth: ^8.0.3
|
||||
uuid: ^8.3.2
|
||||
webextension-polyfill: ^0.8.0
|
||||
ws: ^7.4.6
|
||||
checksum: 052d5dd58951c77733b538d9c392a5aa5b7d87bb600cf04a97e3213048f84936a4446adbf901258417c8eed01dbc68eb2c7117a53b6af7a416ecea975460ffb7
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@metamask/eslint-config-jest@npm:^9.0.0":
|
||||
version: 9.0.0
|
||||
resolution: "@metamask/eslint-config-jest@npm:9.0.0"
|
||||
@ -7537,7 +7555,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/secp256k1@npm:^4.0.1":
|
||||
"@types/secp256k1@npm:^4.0.1, @types/secp256k1@npm:^4.0.3":
|
||||
version: 4.0.3
|
||||
resolution: "@types/secp256k1@npm:4.0.3"
|
||||
dependencies:
|
||||
@ -14292,6 +14310,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"eciesjs@npm:^0.3.15":
|
||||
version: 0.3.16
|
||||
resolution: "eciesjs@npm:0.3.16"
|
||||
dependencies:
|
||||
"@types/secp256k1": ^4.0.3
|
||||
futoin-hkdf: ^1.5.1
|
||||
secp256k1: ^4.0.3
|
||||
checksum: e5e6b8d8d27d8ca4aed89f79c581f7b9bd329551a2332b0a70d61c9b4e378ad98058cd7a16c9cee10cce8bef26a203865dc514ef10d732af3137ba5c13e4254d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ee-first@npm:1.1.1":
|
||||
version: 1.1.1
|
||||
resolution: "ee-first@npm:1.1.1"
|
||||
@ -17475,6 +17504,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"futoin-hkdf@npm:^1.5.1":
|
||||
version: 1.5.1
|
||||
resolution: "futoin-hkdf@npm:1.5.1"
|
||||
checksum: 1912bbf6013e56ff2866590242c9493ab1fe83dc132a175378890b75008ca844524a61dbc20b3fe2c7276ea214589f92f3f0cd48e26d5f5d00c404a6201c5e23
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ganache@npm:^v7.0.4":
|
||||
version: 7.0.4
|
||||
resolution: "ganache@npm:7.0.4"
|
||||
@ -22386,6 +22422,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"jssha@npm:~3.2.0":
|
||||
version: 3.2.0
|
||||
resolution: "jssha@npm:3.2.0"
|
||||
checksum: 2adb8a9a57a79360379e843c0548e240d072c2ef12aef39ef6a784315686bd6f65501e9353fdd2f3a604f64af07e7eab04a0ed92b221cdfea97d671d7b8e14f4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"jsx-ast-utils@npm:^2.4.1 || ^3.0.0":
|
||||
version: 3.3.2
|
||||
resolution: "jsx-ast-utils@npm:3.3.2"
|
||||
@ -23270,7 +23313,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"loglevel@npm:^1.8.1":
|
||||
"loglevel@npm:^1.8.0, loglevel@npm:^1.8.1":
|
||||
version: 1.8.1
|
||||
resolution: "loglevel@npm:1.8.1"
|
||||
checksum: a1a62db40291aaeaef2f612334c49e531bff71cc1d01a2acab689ab80d59e092f852ab164a5aedc1a752fdc46b7b162cb097d8a9eb2cf0b299511106c29af61d
|
||||
@ -24019,6 +24062,7 @@ __metadata:
|
||||
"@metamask/contract-metadata": ^2.2.0
|
||||
"@metamask/controller-utils": ^1.0.0
|
||||
"@metamask/design-tokens": ^1.9.0
|
||||
"@metamask/desktop": ^0.2.0
|
||||
"@metamask/eslint-config": ^9.0.0
|
||||
"@metamask/eslint-config-jest": ^9.0.0
|
||||
"@metamask/eslint-config-mocha": ^9.0.0
|
||||
@ -26179,6 +26223,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"otpauth@npm:^8.0.3":
|
||||
version: 8.0.3
|
||||
resolution: "otpauth@npm:8.0.3"
|
||||
dependencies:
|
||||
jssha: ~3.2.0
|
||||
checksum: bc5f95194c7c942eb1d17fa0d515934803ef7db951a2e89bc31b75dfff03c47403346147b54664861720bdff82e0849ad48914e47fd84776b014d5f7ed73763c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"outpipe@npm:^1.1.0":
|
||||
version: 1.1.1
|
||||
resolution: "outpipe@npm:1.1.1"
|
||||
@ -30405,7 +30458,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"secp256k1@npm:^4.0.0, secp256k1@npm:^4.0.1":
|
||||
"secp256k1@npm:^4.0.0, secp256k1@npm:^4.0.1, secp256k1@npm:^4.0.3":
|
||||
version: 4.0.3
|
||||
resolution: "secp256k1@npm:4.0.3"
|
||||
dependencies:
|
||||
|
Loading…
Reference in New Issue
Block a user