diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index 92ae8d28658b..d00a0542db03 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -32,6 +32,7 @@ cleanContextForImports(); /* eslint-disable import/first */ import log from 'loglevel'; +import { v4 as uuid } from 'uuid'; import { WindowPostMessageStream } from '@metamask/post-message-stream'; import { initializeProvider } from '@metamask/providers/dist/initializeInpageProvider'; import shouldInjectProvider from '../../shared/modules/provider-injection'; @@ -59,5 +60,11 @@ if (shouldInjectProvider()) { connectionStream: metamaskStream, logger: log, shouldShimWeb3: true, + providerInfo: { + uuid: uuid(), + name: process.env.METAMASK_BUILD_NAME, + icon: process.env.METAMASK_BUILD_ICON, + rdns: process.env.METAMASK_BUILD_APP_ID, + }, }); } diff --git a/builds.yml b/builds.yml index 6259e41c2375..8f2060ed9c82 100644 --- a/builds.yml +++ b/builds.yml @@ -232,6 +232,12 @@ env: # Modified in /development/build/scripts.js:@setEnvironmentVariables - METAMASK_BUILD_TYPE # Modified in /development/build/scripts.js:@setEnvironmentVariables + - METAMASK_BUILD_NAME + # Modified in /development/build/scripts.js:@setEnvironmentVariables + - METAMASK_BUILD_APP_ID + # Modified in /development/build/scripts.js:@setEnvironmentVariables + - METAMASK_BUILD_ICON + # Modified in /development/build/scripts.js:@setEnvironmentVariables - NODE_ENV # Defined by node itself # For the purposes of the build system we define it as empty below diff --git a/development/build/manifest.js b/development/build/manifest.js index d9f0f71ca1ff..a12f1c455558 100644 --- a/development/build/manifest.js +++ b/development/build/manifest.js @@ -1,7 +1,7 @@ const { promises: fs } = require('fs'); const path = require('path'); const childProcess = require('child_process'); -const { mergeWith, cloneDeep, capitalize } = require('lodash'); +const { mergeWith, cloneDeep } = require('lodash'); const baseManifest = process.env.ENABLE_MV3 ? require('../../app/manifest/v3/_base.json') @@ -10,7 +10,7 @@ const { loadBuildTypesConfig } = require('../lib/build-type'); const { TASKS, ENVIRONMENT } = require('./constants'); const { createTask, composeSeries } = require('./task'); -const { getEnvironment } = require('./utils'); +const { getEnvironment, getBuildName } = require('./utils'); module.exports = createManifestTasks; @@ -124,10 +124,6 @@ function createManifestTasks({ return; } - const mv3Str = process.env.ENABLE_MV3 ? ' MV3' : ''; - const lavamoatStr = applyLavaMoat ? ' lavamoat' : ''; - const snowStr = shouldIncludeSnow ? ' snow' : ''; - // Get the first 8 characters of the git revision id const gitRevisionStr = childProcess .execSync('git rev-parse HEAD') @@ -135,12 +131,13 @@ function createManifestTasks({ .trim() .substring(0, 8); - const buildName = - buildType === 'mmi' - ? `MetaMask Institutional ${mv3Str}` - : `MetaMask ${capitalize(buildType)}${mv3Str}${lavamoatStr}${snowStr}`; - - manifest.name = buildName; + manifest.name = getBuildName({ + environment, + buildType, + applyLavaMoat, + shouldIncludeSnow, + shouldIncludeMV3: process.env.ENABLE_MV3, + }); manifest.description = `${environment} build from git id: ${gitRevisionStr}`; } diff --git a/development/build/scripts.js b/development/build/scripts.js index fa50a925c09f..f33d509991e0 100644 --- a/development/build/scripts.js +++ b/development/build/scripts.js @@ -40,6 +40,9 @@ const { getEnvironment, logError, wrapAgainstScuttling, + getBuildName, + getBuildAppId, + getBuildIcon, } = require('./utils'); const { @@ -1181,6 +1184,16 @@ async function setEnvironmentVariables({ testing, }), METAMASK_DEBUG: devMode || variables.getMaybe('METAMASK_DEBUG') === true, + METAMASK_BUILD_NAME: getBuildName({ + environment, + buildType, + }), + METAMASK_BUILD_APP_ID: getBuildAppId({ + buildType, + }), + METAMASK_BUILD_ICON: getBuildIcon({ + buildType, + }), METAMASK_ENVIRONMENT: environment, METAMASK_VERSION: version, METAMASK_BUILD_TYPE: buildType, diff --git a/development/build/utils.js b/development/build/utils.js index 9b5bd58e3738..2f814b753014 100644 --- a/development/build/utils.js +++ b/development/build/utils.js @@ -1,8 +1,18 @@ const path = require('path'); +const { readFileSync } = require('fs'); const semver = require('semver'); +const { capitalize } = require('lodash'); const { loadBuildTypesConfig } = require('../lib/build-type'); const { BUILD_TARGETS, ENVIRONMENT } = require('./constants'); +const BUILD_TYPES_TO_SVG_LOGO_PATH = { + main: './app/images/logo/metamask-fox.svg', + beta: './app/build-types/beta/images/logo/metamask-fox.svg', + flask: './app/build-types/flask/images/logo/metamask-fox.svg', + mmi: './app/build-types/mmi/images/logo/mmi-logo.svg', + desktop: './app/build-types/desktop/images/logo/metamask-fox.svg', +}; + /** * Returns whether the current build is a development build or not. * @@ -218,8 +228,69 @@ function getPathInsideNodeModules(packageName, pathToFiles) { return targetPath; } +/** + * Get the name for the current build. + * + * @param {object} options - The build options. + * @param {string} options.buildType - The build type of the current build. + * @param {boolean} options.applyLavaMoat - Flag if lavamoat was applied. + * @param {boolean} options.shouldIncludeSnow - Flag if snow should be included in the build name. + * @param {boolean} options.shouldIncludeMV3 - Flag if mv3 should be included in the build name. + * @param options.environment + * @returns {string} The build name. + */ +function getBuildName({ + environment, + buildType, + applyLavaMoat, + shouldIncludeSnow, + shouldIncludeMV3, +}) { + if (environment === ENVIRONMENT.PRODUCTION) { + return 'MetaMask'; + } + + const mv3Str = shouldIncludeMV3 ? ' MV3' : ''; + const lavamoatStr = applyLavaMoat ? ' lavamoat' : ''; + const snowStr = shouldIncludeSnow ? ' snow' : ''; + + return buildType === 'mmi' + ? `MetaMask Institutional${mv3Str}` + : `MetaMask ${capitalize(buildType)}${mv3Str}${lavamoatStr}${snowStr}`; +} + +/** + * Get the app ID for the current build. Should be valid reverse FQDN. + * + * @param {object} options - The build options. + * @param {string} options.buildType - The build type of the current build. + * @returns {string} The build app ID. + */ +function getBuildAppId({ buildType }) { + const baseDomain = 'io.metamask'; + return buildType === 'main' ? baseDomain : `${baseDomain}.${buildType}`; +} + +/** + * Get the image data uri for the svg icon for the current build. + * + * @param {object} options - The build options. + * @param {string} options.buildType - The build type of the current build. + * @returns {string} The image data uri for the icon. + */ +function getBuildIcon({ buildType }) { + const svgLogoPath = + BUILD_TYPES_TO_SVG_LOGO_PATH[buildType] || + BUILD_TYPES_TO_SVG_LOGO_PATH.main; + const svg = readFileSync(svgLogoPath, 'utf8'); + return `data:image/svg+xml,${encodeURIComponent(svg)}`; +} + module.exports = { getBrowserVersionMap, + getBuildName, + getBuildAppId, + getBuildIcon, getEnvironment, isDevBuild, isTestBuild, diff --git a/package.json b/package.json index 3e8d455a83f5..8004357acee1 100644 --- a/package.json +++ b/package.json @@ -269,7 +269,7 @@ "@metamask/phishing-controller": "^6.0.0", "@metamask/post-message-stream": "^6.2.0", "@metamask/ppom-validator": "^0.5.0", - "@metamask/providers": "^13.0.0", + "@metamask/providers": "^13.1.0", "@metamask/rate-limit-controller": "^3.0.0", "@metamask/rpc-methods": "^3.0.0", "@metamask/safe-event-emitter": "^2.0.0", diff --git a/test/e2e/provider/eip-6963.spec.js b/test/e2e/provider/eip-6963.spec.js new file mode 100644 index 000000000000..751a4e674633 --- /dev/null +++ b/test/e2e/provider/eip-6963.spec.js @@ -0,0 +1,94 @@ +const { strict: assert } = require('assert'); +const FixtureBuilder = require('../fixture-builder'); +const { convertToHexValue, withFixtures, openDapp } = require('../helpers'); + +// https://github.com/thenativeweb/uuidv4/blob/bdcf3a3138bef4fb7c51f389a170666f9012c478/lib/uuidv4.ts#L5 +const UUID_V4_REGEX = + /(?:^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[a-f0-9]{4}-[a-f0-9]{12}$)|(?:^0{8}-0{4}-0{4}-0{4}-0{12}$)/u; + +const SVG_DATA_URI_REGEX = /^data:image\/svg\+xml,/u; + +describe('EIP-6963 Provider', function () { + const ganacheOptions = { + accounts: [ + { + secretKey: + '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC', + balance: convertToHexValue(25000000000000000000), + }, + ], + }; + + it('should respond to the request provider event', async function () { + await withFixtures( + { + dapp: true, + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .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 openDapp(driver); + await driver.executeScript(` + window.announceProviderEvents = [] + window.addEventListener( + "eip6963:announceProvider", + (event) => { + window.announceProviderEvents.push(event) + } + ); + window.dispatchEvent(new Event("eip6963:requestProvider")); + `); + const announceProviderEvents = await driver.executeScript(` + return window.announceProviderEvents.map(event => { + return { + type: event.type, + detail: { + ...event.detail, + provider: Boolean(event.detail.provider) + } + } + }) + `); + + assert.match(announceProviderEvents[0].detail.info.uuid, UUID_V4_REGEX); + delete announceProviderEvents[0].detail.info.uuid; + assert.match( + announceProviderEvents[0].detail.info.icon, + SVG_DATA_URI_REGEX, + ); + delete announceProviderEvents[0].detail.info.icon; + assert.deepStrictEqual(announceProviderEvents, [ + { + type: 'eip6963:announceProvider', + detail: { + info: { + name: 'MetaMask Main', + rdns: 'io.metamask', + }, + provider: true, + }, + }, + ]); + + const request = JSON.stringify({ + jsonrpc: '2.0', + method: 'eth_chainId', + params: [], + id: 0, + }); + const result = await driver.executeScript(` + return window.announceProviderEvents[0].detail.provider.request(${request}) + `); + + assert.equal(result, '0x539'); + }, + ); + }); +}); diff --git a/yarn.lock b/yarn.lock index b3560238caac..3dae9a891314 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4597,9 +4597,9 @@ __metadata: languageName: node linkType: hard -"@metamask/providers@npm:^13.0.0": - version: 13.0.0 - resolution: "@metamask/providers@npm:13.0.0" +"@metamask/providers@npm:^13.0.0, @metamask/providers@npm:^13.1.0": + version: 13.1.0 + resolution: "@metamask/providers@npm:13.1.0" dependencies: "@metamask/json-rpc-engine": "npm:^7.1.1" "@metamask/object-multiplex": "npm:^1.1.0" @@ -4612,7 +4612,7 @@ __metadata: is-stream: "npm:^2.0.0" json-rpc-middleware-stream: "npm:^4.2.1" webextension-polyfill: "npm:^0.10.0" - checksum: c6fe1936741a2b782960f0a12148602754fabe55b75707fd80716d5a42ca4f672d838d1ba36873e96f4afdc5360247e3b737c95b7ca532a74e135218cb65033a + checksum: 2ee1802d92d0fd2c733c5d98137e4f92c77a42fbf008a6b19de25d84d48321502031b82aa66501c4ce9c7e863a82c1866fe477349b48ba1151d4b8c2114233e8 languageName: node linkType: hard @@ -23840,7 +23840,7 @@ __metadata: "@metamask/phishing-warning": "npm:^2.1.0" "@metamask/post-message-stream": "npm:^6.2.0" "@metamask/ppom-validator": "npm:^0.5.0" - "@metamask/providers": "npm:^13.0.0" + "@metamask/providers": "npm:^13.1.0" "@metamask/rate-limit-controller": "npm:^3.0.0" "@metamask/rpc-methods": "npm:^3.0.0" "@metamask/safe-event-emitter": "npm:^2.0.0"