mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 01:47:00 +01:00
add segment implementation of metametrics (#9382)
Co-authored-by: Whymarrh Whitby <whymarrh.whitby@gmail.com> Co-authored-by: Mark Stacey <markjstacey@gmail.com>
This commit is contained in:
parent
9391eac670
commit
8b24f624dd
@ -1,2 +1,3 @@
|
||||
; Extra environment variables
|
||||
INFURA_PROJECT_ID=00000000000
|
||||
SEGMENT_WRITE_KEY=
|
||||
|
@ -18,6 +18,7 @@ To learn how to contribute to the MetaMask project itself, visit our [Internal D
|
||||
- Install dependencies: `yarn`
|
||||
- Copy the `.metamaskrc.dist` file to `.metamaskrc`
|
||||
- Replace the `INFURA_PROJECT_ID` value with your own personal [Infura Project ID](https://infura.io/docs).
|
||||
- If debugging MetaMetrics, you'll need to add a value for `SEGMENT_WRITE_KEY` [Segment write key](https://segment.com/docs/connections/find-writekey/).
|
||||
- Build the project to the `./dist/` folder with `yarn dist`.
|
||||
- Optionally, to start a development build (e.g. with logging and file watching) run `yarn start` instead.
|
||||
- To start the [React DevTools](https://github.com/facebook/react-devtools) and [Redux DevTools Extension](http://extension.remotedev.io)
|
||||
|
@ -17,6 +17,7 @@ const { makeStringTransform } = require('browserify-transform-tools')
|
||||
|
||||
const conf = require('rc')('metamask', {
|
||||
INFURA_PROJECT_ID: process.env.INFURA_PROJECT_ID,
|
||||
SEGMENT_WRITE_KEY: process.env.SEGMENT_WRITE_KEY,
|
||||
})
|
||||
|
||||
const packageJSON = require('../../package.json')
|
||||
@ -316,6 +317,14 @@ function createScriptTasks ({ browserPlatforms, livereload }) {
|
||||
throw new Error('Missing SENTRY_DSN environment variable')
|
||||
}
|
||||
|
||||
// When we're in the 'production' environment we will use a specific key only set in CI
|
||||
// Otherwise we'll use the key from .metamaskrc or from the environment variable. If
|
||||
// the value of SEGMENT_WRITE_KEY that we envify is undefined then no events will be tracked
|
||||
// in the build. This is intentional so that developers can contribute to MetaMask without
|
||||
// inflating event volume.
|
||||
const SEGMENT_PROD_WRITE_KEY = opts.testing ? undefined : process.env.SEGMENT_PROD_WRITE_KEY
|
||||
const SEGMENT_DEV_WRITE_KEY = opts.testing ? undefined : conf.SEGMENT_WRITE_KEY
|
||||
|
||||
// Inject variables into bundle
|
||||
bundler.transform(envify({
|
||||
METAMASK_DEBUG: opts.devMode,
|
||||
@ -333,6 +342,7 @@ function createScriptTasks ({ browserPlatforms, livereload }) {
|
||||
? '00000000000000000000000000000000'
|
||||
: conf.INFURA_PROJECT_ID
|
||||
),
|
||||
SEGMENT_WRITE_KEY: environment === 'production' ? SEGMENT_PROD_WRITE_KEY : SEGMENT_DEV_WRITE_KEY,
|
||||
}), {
|
||||
global: true,
|
||||
})
|
||||
|
@ -82,6 +82,7 @@
|
||||
"@sentry/integrations": "^5.11.1",
|
||||
"@zxing/library": "^0.8.0",
|
||||
"abortcontroller-polyfill": "^1.4.0",
|
||||
"analytics-node": "^3.4.0-beta.2",
|
||||
"await-semaphore": "^0.1.1",
|
||||
"bignumber.js": "^4.1.0",
|
||||
"bip39": "^2.2.0",
|
||||
|
231
ui/app/contexts/metametrics.new.js
Normal file
231
ui/app/contexts/metametrics.new.js
Normal file
@ -0,0 +1,231 @@
|
||||
/**
|
||||
* This file is intended to be renamed to metametrics.js once the conversion is complete.
|
||||
* MetaMetrics is our own brand, and should remain aptly named regardless of the underlying
|
||||
* metrics system. This file implements Segment analytics tracking.
|
||||
*/
|
||||
import React, { useRef, Component, createContext, useEffect, useCallback } from 'react'
|
||||
import { useSelector } from 'react-redux'
|
||||
import PropTypes from 'prop-types'
|
||||
import { useLocation, matchPath, useRouteMatch } from 'react-router-dom'
|
||||
import { captureException, captureMessage } from '@sentry/browser'
|
||||
|
||||
import { omit } from 'lodash'
|
||||
import {
|
||||
getCurrentNetworkId,
|
||||
} from '../selectors/selectors'
|
||||
|
||||
import { getEnvironmentType } from '../../../app/scripts/lib/util'
|
||||
import {
|
||||
sendCountIsTrackable,
|
||||
segment,
|
||||
METAMETRICS_ANONYMOUS_ID,
|
||||
} from '../helpers/utils/metametrics.util'
|
||||
import { PATH_NAME_MAP } from '../helpers/constants/routes'
|
||||
import { getCurrentLocale } from '../ducks/metamask/metamask'
|
||||
import { txDataSelector } from '../selectors'
|
||||
|
||||
export const MetaMetricsContext = createContext(() => {
|
||||
captureException(
|
||||
Error(`MetaMetrics context function was called from a react node that is not a descendant of a MetaMetrics context provider`),
|
||||
)
|
||||
})
|
||||
|
||||
const PATHS_TO_CHECK = Object.keys(PATH_NAME_MAP)
|
||||
|
||||
function useSegmentContext () {
|
||||
const match = useRouteMatch({ path: PATHS_TO_CHECK, exact: true, strict: true })
|
||||
const locale = useSelector(getCurrentLocale)
|
||||
const txData = useSelector(txDataSelector) || {}
|
||||
const confirmTransactionOrigin = txData.origin
|
||||
|
||||
const referrer = confirmTransactionOrigin ? {
|
||||
url: confirmTransactionOrigin,
|
||||
} : undefined
|
||||
|
||||
let version = global.platform.getVersion()
|
||||
if (process.env.METAMASK_ENVIRONMENT !== 'production') {
|
||||
version = `${version}-${process.env.METAMASK_ENVIRONMENT}`
|
||||
}
|
||||
|
||||
const page = match ? {
|
||||
path: match.path,
|
||||
title: PATH_NAME_MAP[match.path],
|
||||
url: match.path,
|
||||
} : undefined
|
||||
|
||||
return {
|
||||
app: {
|
||||
version,
|
||||
name: 'MetaMask Extension',
|
||||
},
|
||||
locale: locale.replace('_', '-'),
|
||||
page,
|
||||
referrer,
|
||||
userAgent: window.navigator.userAgent,
|
||||
}
|
||||
}
|
||||
|
||||
export function MetaMetricsProvider ({ children }) {
|
||||
const network = useSelector(getCurrentNetworkId)
|
||||
const metaMetricsId = useSelector((state) => state.metamask.metaMetricsId)
|
||||
const participateInMetaMetrics = useSelector((state) => state.metamask.participateInMetaMetrics)
|
||||
const metaMetricsSendCount = useSelector((state) => state.metamask.metaMetricsSendCount)
|
||||
const location = useLocation()
|
||||
const context = useSegmentContext()
|
||||
|
||||
// Used to prevent double tracking page calls
|
||||
const previousMatch = useRef()
|
||||
|
||||
/**
|
||||
* Anytime the location changes, track a page change with segment.
|
||||
* Previously we would manually track changes to history and keep a
|
||||
* reference to the previous url, but with page tracking we can see
|
||||
* which page the user is on and their navigation path.
|
||||
*/
|
||||
useEffect(() => {
|
||||
const environmentType = getEnvironmentType()
|
||||
if (
|
||||
(participateInMetaMetrics === null && location.pathname.startsWith('/initialize')) ||
|
||||
participateInMetaMetrics
|
||||
) {
|
||||
// Events that happen during initialization before the user opts into MetaMetrics will be anonymous
|
||||
const idTrait = metaMetricsId ? 'userId' : 'anonymousId'
|
||||
const idValue = metaMetricsId ?? METAMETRICS_ANONYMOUS_ID
|
||||
const match = matchPath(location.pathname, { path: PATHS_TO_CHECK, exact: true, strict: true })
|
||||
if (
|
||||
match &&
|
||||
previousMatch.current !== match.path &&
|
||||
// If we're in a popup or notification we don't want the initial home route to track
|
||||
!(
|
||||
(environmentType === 'popup' || environmentType === 'notification') &&
|
||||
match.path === '/' &&
|
||||
previousMatch.current === undefined
|
||||
)
|
||||
) {
|
||||
const { path, params } = match
|
||||
const name = PATH_NAME_MAP[path]
|
||||
segment.page({
|
||||
[idTrait]: idValue,
|
||||
name,
|
||||
properties: {
|
||||
// We do not want to send addresses or accounts in any events
|
||||
// Some routes include these as params.
|
||||
params: omit(params, ['account', 'address']),
|
||||
network,
|
||||
environment_type: environmentType,
|
||||
},
|
||||
context,
|
||||
})
|
||||
} else if (location.pathname !== '/confirm-transaction') {
|
||||
// We have more specific pages for each type of transaction confirmation
|
||||
// The user lands on /confirm-transaction first, then is redirected based on
|
||||
// the contents of state.
|
||||
captureMessage(`${location.pathname} would have issued a page track event to segment, but no route match was found`)
|
||||
}
|
||||
previousMatch.current = match?.path
|
||||
}
|
||||
}, [location, context, network, metaMetricsId, participateInMetaMetrics])
|
||||
|
||||
/**
|
||||
* track a metametrics event using segment
|
||||
* e.g metricsEvent({ event: 'Unlocked MetaMask', category: 'Navigation' })
|
||||
*
|
||||
* @param {object} config - configuration object for the event to track
|
||||
* @param {string} config.event - event name to track
|
||||
* @param {string} config.category - category to associate event to
|
||||
* @param {boolean} [config.isOptIn] - happened during opt in/out workflow
|
||||
* @param {object} [config.properties] - object of custom values to track, snake_case
|
||||
* @param {number} [config.revenue] - amount of currency that event creates in revenue for MetaMask
|
||||
* @param {string} [config.currency] - ISO 4127 format currency for events with revenue, defaults to US dollars
|
||||
* @param {number} [config.value] - Abstract "value" that this event has for MetaMask.
|
||||
* @return {undefined}
|
||||
*/
|
||||
const trackEvent = useCallback(
|
||||
(config = {}) => {
|
||||
const { event, category, isOptIn = false, properties = {}, revenue, value, currency } = config
|
||||
if (!event) {
|
||||
// Event name is required for tracking an event
|
||||
throw new Error('MetaMetrics trackEvent function must be provided a payload with an "event" key')
|
||||
}
|
||||
if (!category) {
|
||||
// Category must be supplied for every tracking event
|
||||
throw new Error('MetaMetrics events must be provided a category')
|
||||
}
|
||||
const environmentType = getEnvironmentType()
|
||||
|
||||
let excludeMetaMetricsId = config.excludeMetaMetricsId ?? false
|
||||
|
||||
// This is carried over from the old implementation, and will likely need
|
||||
// to be updated to work with the new tracking plan. I think we should use
|
||||
// a config setting for this instead of trying to match the event name
|
||||
const isSendFlow = Boolean(event.match(/^send|^confirm/u))
|
||||
if (isSendFlow && !sendCountIsTrackable(metaMetricsSendCount + 1)) {
|
||||
excludeMetaMetricsId = true
|
||||
}
|
||||
const idTrait = excludeMetaMetricsId ? 'anonymousId' : 'userId'
|
||||
const idValue = excludeMetaMetricsId ? METAMETRICS_ANONYMOUS_ID : metaMetricsId
|
||||
|
||||
if (participateInMetaMetrics || isOptIn) {
|
||||
segment.track({
|
||||
[idTrait]: idValue,
|
||||
event,
|
||||
properties: {
|
||||
...omit(properties, ['revenue', 'currency', 'value']),
|
||||
revenue,
|
||||
value,
|
||||
currency,
|
||||
category,
|
||||
network,
|
||||
environment_type: environmentType,
|
||||
},
|
||||
context,
|
||||
})
|
||||
}
|
||||
|
||||
return undefined
|
||||
}, [
|
||||
context,
|
||||
network,
|
||||
metaMetricsId,
|
||||
metaMetricsSendCount,
|
||||
participateInMetaMetrics,
|
||||
],
|
||||
)
|
||||
|
||||
return (
|
||||
<MetaMetricsContext.Provider value={trackEvent}>
|
||||
{children}
|
||||
</MetaMetricsContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
MetaMetricsProvider.propTypes = { children: PropTypes.node }
|
||||
|
||||
export class LegacyMetaMetricsProvider extends Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.node,
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
children: undefined,
|
||||
}
|
||||
|
||||
static contextType = MetaMetricsContext
|
||||
|
||||
static childContextTypes = {
|
||||
// This has to be different than the type name for the old metametrics file
|
||||
// using the same name would result in whichever was lower in the tree to be
|
||||
// used.
|
||||
trackEvent: PropTypes.func,
|
||||
}
|
||||
|
||||
getChildContext () {
|
||||
return {
|
||||
trackEvent: this.context,
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
return this.props.children
|
||||
}
|
||||
}
|
@ -54,6 +54,63 @@ const SIGNATURE_REQUEST_PATH = '/signature-request'
|
||||
const DECRYPT_MESSAGE_REQUEST_PATH = '/decrypt-message-request'
|
||||
const ENCRYPTION_PUBLIC_KEY_REQUEST_PATH = '/encryption-public-key-request'
|
||||
|
||||
// Used to pull a convenient name for analytics tracking events. The key must
|
||||
// be react-router ready path, and can include params such as :id for popup windows
|
||||
const PATH_NAME_MAP = {
|
||||
[DEFAULT_ROUTE]: 'Home',
|
||||
[UNLOCK_ROUTE]: 'Unlock Page',
|
||||
[LOCK_ROUTE]: 'Lock Page',
|
||||
[`${ASSET_ROUTE}/:asset`]: `Asset Page`,
|
||||
[SETTINGS_ROUTE]: 'Settings Page',
|
||||
[GENERAL_ROUTE]: 'General Settings Page',
|
||||
[ADVANCED_ROUTE]: 'Advanced Settings Page',
|
||||
[SECURITY_ROUTE]: 'Security Settings Page',
|
||||
[ABOUT_US_ROUTE]: 'About Us Page',
|
||||
[ALERTS_ROUTE]: 'Alerts Settings Page',
|
||||
[NETWORKS_ROUTE]: 'Network Settings Page',
|
||||
[CONTACT_LIST_ROUTE]: 'Contact List Settings Page',
|
||||
[`${CONTACT_EDIT_ROUTE}/:address`]: 'Edit Contact Settings Page',
|
||||
[CONTACT_ADD_ROUTE]: 'Add Contact Settings Page',
|
||||
[`${CONTACT_VIEW_ROUTE}/:address`]: 'View Contact Settings Page',
|
||||
[CONTACT_MY_ACCOUNTS_ROUTE]: 'My Accounts List Settings Page',
|
||||
[`${CONTACT_MY_ACCOUNTS_VIEW_ROUTE}/:account`]: 'View Account Settings Page',
|
||||
[`${CONTACT_MY_ACCOUNTS_EDIT_ROUTE}/:account`]: 'Edit Account Settings Page',
|
||||
[REVEAL_SEED_ROUTE]: 'Reveal Seed Page',
|
||||
[MOBILE_SYNC_ROUTE]: 'Sync With Mobile Page',
|
||||
[RESTORE_VAULT_ROUTE]: 'Restore Vault Page',
|
||||
[ADD_TOKEN_ROUTE]: 'Add Token Page',
|
||||
[CONFIRM_ADD_TOKEN_ROUTE]: 'Confirm Add Token Page',
|
||||
[CONFIRM_ADD_SUGGESTED_TOKEN_ROUTE]: 'Confirm Add Suggested Token Page',
|
||||
[NEW_ACCOUNT_ROUTE]: 'New Account Page',
|
||||
[IMPORT_ACCOUNT_ROUTE]: 'Import Account Page',
|
||||
[CONNECT_HARDWARE_ROUTE]: 'Connect Hardware Wallet Page',
|
||||
[SEND_ROUTE]: 'Send Page',
|
||||
[`${CONNECT_ROUTE}/:id`]: 'Connect To Site Confirmation Page',
|
||||
[`${CONNECT_ROUTE}/:id${CONNECT_CONFIRM_PERMISSIONS_ROUTE}`]: 'Grant Connected Site Permissions Confirmation Page',
|
||||
[CONNECTED_ROUTE]: 'Sites Connected To This Account Page',
|
||||
[CONNECTED_ACCOUNTS_ROUTE]: 'Accounts Connected To This Site Page',
|
||||
[`${CONFIRM_TRANSACTION_ROUTE}/:id${CONFIRM_TOKEN_METHOD_PATH}`]: 'Confirm Token Method Transaction Page',
|
||||
[`${CONFIRM_TRANSACTION_ROUTE}/:id${CONFIRM_SEND_ETHER_PATH}`]: 'Confirm Send Ether Transaction Page',
|
||||
[`${CONFIRM_TRANSACTION_ROUTE}/:id${CONFIRM_SEND_TOKEN_PATH}`]: 'Confirm Send Token Transaction Page',
|
||||
[`${CONFIRM_TRANSACTION_ROUTE}/:id${CONFIRM_DEPLOY_CONTRACT_PATH}`]: 'Confirm Deploy Contract Transaction Page',
|
||||
[`${CONFIRM_TRANSACTION_ROUTE}/:id${CONFIRM_APPROVE_PATH}`]: 'Confirm Approve Transaction Page',
|
||||
[`${CONFIRM_TRANSACTION_ROUTE}/:id${CONFIRM_TRANSFER_FROM_PATH}`]: 'Confirm Transfer From Transaction Page',
|
||||
[`${CONFIRM_TRANSACTION_ROUTE}/:id${SIGNATURE_REQUEST_PATH}`]: 'Signature Request Page',
|
||||
[`${CONFIRM_TRANSACTION_ROUTE}/:id${DECRYPT_MESSAGE_REQUEST_PATH}`]: 'Decrypt Message Request Page',
|
||||
[`${CONFIRM_TRANSACTION_ROUTE}/:id${ENCRYPTION_PUBLIC_KEY_REQUEST_PATH}`]: 'Encryption Public Key Request Page',
|
||||
[INITIALIZE_ROUTE]: 'Initialization Page',
|
||||
[INITIALIZE_WELCOME_ROUTE]: 'Install Welcome Page',
|
||||
[INITIALIZE_UNLOCK_ROUTE]: 'Initialization Unlock page',
|
||||
[INITIALIZE_CREATE_PASSWORD_ROUTE]: 'Initialization Create Password Page',
|
||||
[INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE]: 'Initialization Import Account With Seed Phrase Page',
|
||||
[INITIALIZE_SELECT_ACTION_ROUTE]: 'Initialization Choose Restore or New Account Page',
|
||||
[INITIALIZE_SEED_PHRASE_ROUTE]: 'Initialization Seed Phrase Page',
|
||||
[INITIALIZE_BACKUP_SEED_PHRASE_ROUTE]: 'Initialization Backup Seed Phrase Page',
|
||||
[INITIALIZE_END_OF_FLOW_ROUTE]: 'End of Initialization Page',
|
||||
[INITIALIZE_CONFIRM_SEED_PHRASE_ROUTE]: 'Initialization Confirm Seed Phrase Page',
|
||||
[INITIALIZE_METAMETRICS_OPT_IN_ROUTE]: 'MetaMetrics Opt In Page',
|
||||
}
|
||||
|
||||
export {
|
||||
DEFAULT_ROUTE,
|
||||
ALERTS_ROUTE,
|
||||
@ -108,4 +165,5 @@ export {
|
||||
CONNECT_CONFIRM_PERMISSIONS_ROUTE,
|
||||
CONNECTED_ROUTE,
|
||||
CONNECTED_ACCOUNTS_ROUTE,
|
||||
PATH_NAME_MAP,
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* eslint camelcase: 0 */
|
||||
|
||||
import ethUtil from 'ethereumjs-util'
|
||||
import Analytics from 'analytics-node'
|
||||
|
||||
const inDevelopment = process.env.METAMASK_DEBUG || process.env.IN_TEST
|
||||
|
||||
@ -73,6 +74,8 @@ const customDimensionsNameIdMap = {
|
||||
[METAMETRICS_CUSTOM_VERSION]: 11,
|
||||
}
|
||||
|
||||
export const METAMETRICS_ANONYMOUS_ID = '0x0000000000000000'
|
||||
|
||||
function composeUrlRefParamAddition (previousPath, confirmTransactionOrigin) {
|
||||
const externalOrigin = confirmTransactionOrigin && confirmTransactionOrigin !== 'metamask'
|
||||
return `&urlref=${externalOrigin ? 'EXTERNAL' : encodeURIComponent(`${METAMETRICS_TRACKING_URL}${previousPath}`)}`
|
||||
@ -232,3 +235,25 @@ const trackableSendCounts = {
|
||||
export function sendCountIsTrackable (sendCount) {
|
||||
return Boolean(trackableSendCounts[sendCount])
|
||||
}
|
||||
|
||||
const flushAt = inDevelopment ? 1 : undefined
|
||||
|
||||
const segmentNoop = {
|
||||
track () {
|
||||
// noop
|
||||
},
|
||||
page () {
|
||||
// noop
|
||||
},
|
||||
identify () {
|
||||
// noop
|
||||
},
|
||||
}
|
||||
|
||||
// We do not want to track events on development builds unless specifically
|
||||
// provided a SEGMENT_WRITE_KEY. This also holds true for test environments and
|
||||
// E2E, which is handled in the build process by never providing the SEGMENT_WRITE_KEY
|
||||
// which process.env.IN_TEST is true
|
||||
export const segment = process.env.SEGMENT_WRITE_KEY
|
||||
? new Analytics(process.env.SEGMENT_WRITE_KEY, { flushAt })
|
||||
: segmentNoop
|
||||
|
@ -1,8 +1,30 @@
|
||||
import { useContext, useCallback } from 'react'
|
||||
import { MetaMetricsContext } from '../contexts/metametrics'
|
||||
import { MetaMetricsContext as NewMetaMetricsContext } from '../contexts/metametrics.new'
|
||||
import { useEqualityCheck } from './useEqualityCheck'
|
||||
|
||||
export function useMetricEvent (config = {}, overrides = {}) {
|
||||
const metricsEvent = useContext(MetaMetricsContext)
|
||||
const trackEvent = useCallback(() => metricsEvent(config, overrides), [config, metricsEvent, overrides])
|
||||
return trackEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* track a metametrics event using segment
|
||||
* e.g metricsEvent({ event: 'Unlocked MetaMask', category: 'Navigation' })
|
||||
*
|
||||
* @param {object} config - configuration object for the event to track
|
||||
* @param {string} config.event - event name to track
|
||||
* @param {string} config.category - category to associate event to
|
||||
* @param {boolean} [config.isOptIn] - happened during opt in/out workflow
|
||||
* @param {object} [config.properties] - object of custom values to track, snake_case
|
||||
* @param {number} [config.revenue] - amount of currency that event creates in revenue for MetaMask
|
||||
* @param {string} [config.currency] - ISO 4127 format currency for events with revenue, defaults to US dollars
|
||||
* @param {number} [config.value] - Abstract "value" that this event has for MetaMask.
|
||||
* @return {() => undefined} function to execute the tracking event
|
||||
*/
|
||||
export function useNewMetricEvent (config) {
|
||||
const memoizedConfig = useEqualityCheck(config)
|
||||
const metricsEvent = useContext(NewMetaMetricsContext)
|
||||
return useCallback(() => metricsEvent(memoizedConfig), [metricsEvent, memoizedConfig])
|
||||
}
|
||||
|
@ -5,6 +5,10 @@ import { HashRouter } from 'react-router-dom'
|
||||
import * as Sentry from '@sentry/browser'
|
||||
import { I18nProvider, LegacyI18nProvider } from '../contexts/i18n'
|
||||
import { MetaMetricsProvider, LegacyMetaMetricsProvider } from '../contexts/metametrics'
|
||||
import {
|
||||
MetaMetricsProvider as NewMetaMetricsProvider,
|
||||
LegacyMetaMetricsProvider as NewLegacyMetaMetricsProvider,
|
||||
} from '../contexts/metametrics.new'
|
||||
import ErrorPage from './error'
|
||||
import Routes from './routes'
|
||||
|
||||
@ -43,11 +47,15 @@ class Index extends PureComponent {
|
||||
<HashRouter hashType="noslash">
|
||||
<MetaMetricsProvider>
|
||||
<LegacyMetaMetricsProvider>
|
||||
<I18nProvider>
|
||||
<LegacyI18nProvider>
|
||||
<Routes />
|
||||
</LegacyI18nProvider>
|
||||
</I18nProvider>
|
||||
<NewMetaMetricsProvider>
|
||||
<NewLegacyMetaMetricsProvider>
|
||||
<I18nProvider>
|
||||
<LegacyI18nProvider>
|
||||
<Routes />
|
||||
</LegacyI18nProvider>
|
||||
</I18nProvider>
|
||||
</NewLegacyMetaMetricsProvider>
|
||||
</NewMetaMetricsProvider>
|
||||
</LegacyMetaMetricsProvider>
|
||||
</MetaMetricsProvider>
|
||||
</HashRouter>
|
||||
|
81
yarn.lock
81
yarn.lock
@ -2222,6 +2222,14 @@
|
||||
redux-thunk "^2.3.0"
|
||||
reselect "^4.0.0"
|
||||
|
||||
"@segment/loosely-validate-event@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@segment/loosely-validate-event/-/loosely-validate-event-2.0.0.tgz#87dfc979e5b4e7b82c5f1d8b722dfd5d77644681"
|
||||
integrity sha512-ZMCSfztDBqwotkl848ODgVcAmN4OItEWDCkshcKz0/W6gGSQayuuCtWV/MlodFivAZD793d6UgANd6wCXUfrIw==
|
||||
dependencies:
|
||||
component-type "^1.2.1"
|
||||
join-component "^1.1.0"
|
||||
|
||||
"@sentry/browser@^5.11.1":
|
||||
version "5.11.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.11.1.tgz#337ffcb52711b23064c847a07629e966f54a5ebb"
|
||||
@ -3750,6 +3758,20 @@ amdefine@>=0.0.4:
|
||||
resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
|
||||
integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=
|
||||
|
||||
analytics-node@^3.4.0-beta.2:
|
||||
version "3.4.0-beta.2"
|
||||
resolved "https://registry.yarnpkg.com/analytics-node/-/analytics-node-3.4.0-beta.2.tgz#d4921927c2253dcc2fcbf18604dac2ee098a9b52"
|
||||
integrity sha512-wjdCQQk412RBckuqGtyY7tdxaRpG7HLD0iBQrJBc7aUzHFNYyEbz3kepaUmNd5+ZbAGDqfnvKVsFO5DmzI1KNA==
|
||||
dependencies:
|
||||
"@segment/loosely-validate-event" "^2.0.0"
|
||||
axios "^0.19.0"
|
||||
axios-retry "^3.0.2"
|
||||
lodash.isstring "^4.0.1"
|
||||
md5 "^2.2.1"
|
||||
ms "^2.0.0"
|
||||
remove-trailing-slash "^0.1.0"
|
||||
uuid "^3.2.1"
|
||||
|
||||
ansi-align@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f"
|
||||
@ -4629,6 +4651,20 @@ aws4@^1.8.0:
|
||||
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f"
|
||||
integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==
|
||||
|
||||
axios-retry@^3.0.2:
|
||||
version "3.1.8"
|
||||
resolved "https://registry.yarnpkg.com/axios-retry/-/axios-retry-3.1.8.tgz#ffcfed757e1fab8cbf832f8505bb0e0af47c520c"
|
||||
integrity sha512-yPw5Y4Bg6Dgmhm35KaJFtlh23s1TecW0HsUerK4/IS1UKl0gtN2aJqdEKtVomiOS/bDo5w4P3sqgki/M10eF8Q==
|
||||
dependencies:
|
||||
is-retry-allowed "^1.1.0"
|
||||
|
||||
axios@^0.19.0:
|
||||
version "0.19.2"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27"
|
||||
integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==
|
||||
dependencies:
|
||||
follow-redirects "1.5.10"
|
||||
|
||||
babel-code-frame@^6.16.0, babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
|
||||
version "6.26.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
|
||||
@ -6846,6 +6882,11 @@ chardet@^0.7.0:
|
||||
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
|
||||
integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
|
||||
|
||||
charenc@0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
|
||||
integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=
|
||||
|
||||
check-error@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
|
||||
@ -7428,6 +7469,11 @@ component-inherit@0.0.3:
|
||||
resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143"
|
||||
integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=
|
||||
|
||||
component-type@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/component-type/-/component-type-1.2.1.tgz#8a47901700238e4fc32269771230226f24b415a9"
|
||||
integrity sha1-ikeQFwAjjk/DIml3EjAibyS0Fak=
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
@ -7905,6 +7951,11 @@ cross-spawn@^7.0.0:
|
||||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
crypt@0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
|
||||
integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
|
||||
|
||||
crypto-browserify@3.12.0, crypto-browserify@^3.0.0, crypto-browserify@^3.11.0:
|
||||
version "3.12.0"
|
||||
resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
|
||||
@ -8484,7 +8535,7 @@ debug@2, debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, de
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@3.1.0, debug@3.X, debug@~3.1.0:
|
||||
debug@3.1.0, debug@3.X, debug@=3.1.0, debug@~3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
|
||||
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
|
||||
@ -12032,6 +12083,13 @@ focus-lock@^0.6.6:
|
||||
resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.6.6.tgz#98119a755a38cfdbeda0280eaa77e307eee850c7"
|
||||
integrity sha512-Dx69IXGCq1qsUExWuG+5wkiMqVM/zGx/reXSJSLogECwp3x6KeNQZ+NAetgxEFpnC41rD8U3+jRCW68+LNzdtw==
|
||||
|
||||
follow-redirects@1.5.10:
|
||||
version "1.5.10"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a"
|
||||
integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==
|
||||
dependencies:
|
||||
debug "=3.1.0"
|
||||
|
||||
for-each@^0.3.3, for-each@~0.3.3:
|
||||
version "0.3.3"
|
||||
resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"
|
||||
@ -15001,7 +15059,7 @@ is-boolean-object@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.0.tgz#98f8b28030684219a95f375cfbd88ce3405dff93"
|
||||
integrity sha1-mPiygDBoQhmpXzdc+9iM40Bd/5M=
|
||||
|
||||
is-buffer@^1.0.2, is-buffer@^1.1.0, is-buffer@^1.1.5:
|
||||
is-buffer@^1.0.2, is-buffer@^1.1.0, is-buffer@^1.1.5, is-buffer@~1.1.6:
|
||||
version "1.1.6"
|
||||
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
||||
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
|
||||
@ -15836,6 +15894,11 @@ joi-browser@^13.4.0:
|
||||
resolved "https://registry.yarnpkg.com/joi-browser/-/joi-browser-13.4.0.tgz#b72ba61b610e3f58e51b563a14e0f5225cfb6896"
|
||||
integrity sha512-TfzJd2JaJ/lg/gU+q5j9rLAjnfUNF9DUmXTP9w+GfmG79LjFOXFeM7hIFuXCBcZCivUDFwd9l1btTV9rhHumtQ==
|
||||
|
||||
join-component@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/join-component/-/join-component-1.1.0.tgz#b8417b750661a392bee2c2537c68b2a9d4977cd5"
|
||||
integrity sha1-uEF7dQZho5K+4sJTfGiyqdSXfNU=
|
||||
|
||||
jpegtran-bin@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jpegtran-bin/-/jpegtran-bin-4.0.0.tgz#d00aed809fba7aa6f30817e59eee4ddf198f8f10"
|
||||
@ -17966,6 +18029,15 @@ md5.js@^1.3.4:
|
||||
inherits "^2.0.1"
|
||||
safe-buffer "^5.1.2"
|
||||
|
||||
md5@^2.2.1:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f"
|
||||
integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==
|
||||
dependencies:
|
||||
charenc "0.0.2"
|
||||
crypt "0.0.2"
|
||||
is-buffer "~1.1.6"
|
||||
|
||||
mdast-util-compact@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/mdast-util-compact/-/mdast-util-compact-2.0.1.tgz#cabc69a2f43103628326f35b1acf735d55c99490"
|
||||
@ -23108,6 +23180,11 @@ remove-trailing-separator@^1.0.1, remove-trailing-separator@^1.1.0:
|
||||
resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
|
||||
integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8=
|
||||
|
||||
remove-trailing-slash@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/remove-trailing-slash/-/remove-trailing-slash-0.1.0.tgz#1498e5df0984c27e49b76ebf06887ca2d01150d2"
|
||||
integrity sha1-FJjl3wmEwn5Jt26/Boh8otARUNI=
|
||||
|
||||
renderkid@^2.0.1:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-2.0.3.tgz#380179c2ff5ae1365c522bf2fcfcff01c5b74149"
|
||||
|
Loading…
Reference in New Issue
Block a user