|
|
|
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 - 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
|
|
|
|
}
|
|
|
|
}
|