1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-30 16:18:07 +01:00
metamask-extension/ui/app/contexts/metametrics.js
2020-10-26 14:05:57 -05:00

152 lines
4.9 KiB
JavaScript

import React, { Component, createContext, useEffect, useCallback, useState, useMemo } from 'react'
import { useSelector } from 'react-redux'
import PropTypes from 'prop-types'
import { useHistory } from 'react-router-dom'
import { captureException } from '@sentry/browser'
import {
getCurrentNetworkId,
getAccountType,
getNumberOfAccounts,
getNumberOfTokens,
getCurrentChainId,
} from '../selectors/selectors'
import { getSendToken } from '../selectors/send'
import {
txDataSelector,
} from '../selectors/confirm-transaction'
import { getEnvironmentType } from '../../../app/scripts/lib/util'
import { getTrackMetaMetricsEvent } from '../../../shared/modules/metametrics'
import { getCurrentLocale } from '../ducks/metamask/metamask'
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`),
)
})
export function MetaMetricsProvider ({ children }) {
const txData = useSelector(txDataSelector) || {}
const network = useSelector(getCurrentNetworkId)
const environmentType = getEnvironmentType()
const chainId = useSelector(getCurrentChainId)
const locale = useSelector(getCurrentLocale)
const activeCurrency = useSelector(getSendToken)?.symbol
const accountType = useSelector(getAccountType)
const confirmTransactionOrigin = txData.origin
const metaMetricsId = useSelector((state) => state.metamask.metaMetricsId)
const participateInMetaMetrics = useSelector((state) => state.metamask.participateInMetaMetrics)
const metaMetricsSendCount = useSelector((state) => state.metamask.metaMetricsSendCount)
const numberOfTokens = useSelector(getNumberOfTokens)
const numberOfAccounts = useSelector(getNumberOfAccounts)
const history = useHistory()
const [state, setState] = useState(() => ({
currentPath: (new URL(window.location.href)).pathname,
previousPath: '',
}))
const { currentPath } = state
useEffect(() => {
const unlisten = history.listen(() => setState((prevState) => ({
currentPath: (new URL(window.location.href)).pathname,
previousPath: prevState.currentPath,
})))
// remove this listener if the component is no longer mounted
return unlisten
}, [history])
/**
* track a metametrics event
*
* @param {import('../../../shared/modules/metametrics').MetaMetricsEventPayload} - payload for event
* @returns undefined
*/
const trackEvent = useMemo(() => {
const referrer = confirmTransactionOrigin ? { url: confirmTransactionOrigin } : undefined
const page = {
path: currentPath,
}
return getTrackMetaMetricsEvent(global.platform.getVersion(), () => ({
context: {
referrer,
page,
},
environmentType,
locale: locale.replace('_', '-'),
network,
chainId,
participateInMetaMetrics,
metaMetricsId,
metaMetricsSendCount,
}))
}, [network, chainId, locale, environmentType, participateInMetaMetrics, currentPath, confirmTransactionOrigin, metaMetricsId, metaMetricsSendCount])
const metricsEvent = useCallback((config = {}, overrides = {}) => {
const { eventOpts = {} } = config
return trackEvent({
event: eventOpts.name,
category: eventOpts.category,
isOptIn: config.isOptIn,
excludeMetaMetricsId: eventOpts.excludeMetaMetricsId ?? overrides.excludeMetaMetricsId ?? false,
metaMetricsId: config.metaMetricsId,
matomoEvent: true,
properties: {
action: eventOpts.action,
number_of_tokens: numberOfTokens,
number_of_accounts: numberOfAccounts,
active_currency: activeCurrency,
account_type: accountType,
is_new_visit: config.is_new_visit,
// the properties coming from this key will not match our standards for
// snake_case on properties, and they may be redundant and/or not in the
// proper location (origin not as a referrer, for example). This is a temporary
// solution to not lose data, and the entire event system will be reworked in
// forthcoming PRs to deprecate the old Matomo events in favor of the new schema.
...config.customVariables,
},
})
}, [
accountType,
activeCurrency,
numberOfTokens,
numberOfAccounts,
trackEvent,
])
return (
<MetaMetricsContext.Provider value={metricsEvent}>
{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 = {
metricsEvent: PropTypes.func,
}
getChildContext () {
return {
metricsEvent: this.context,
}
}
render () {
return this.props.children
}
}