1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 01:39:44 +01:00

Remove usages of useNewMetricEvent hook (#13955)

This commit is contained in:
VSaric 2022-03-25 14:21:29 +01:00 committed by GitHub
parent 69cba6d9fb
commit 5564176d72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 396 additions and 356 deletions

View File

@ -15,7 +15,6 @@ import {
getSelectedIdentity,
} from '../../../selectors';
import { useI18nContext } from '../../../hooks/useI18nContext';
import { useNewMetricEvent } from '../../../hooks/useMetricEvent';
import { getEnvironmentType } from '../../../../app/scripts/lib/util';
import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../shared/constants/app';
import { MetaMetricsContext } from '../../../contexts/metametrics.new';
@ -35,16 +34,6 @@ export default function AccountOptionsMenu({ anchorElement, onClose }) {
const blockExplorerUrlSubTitle = getURLHostName(blockExplorerUrl);
const trackEvent = useContext(MetaMetricsContext);
const blockExplorerLinkClickedEvent = useNewMetricEvent({
category: 'Navigation',
event: 'Clicked Block Explorer Link',
properties: {
link_type: 'Account Tracker',
action: 'Account Options',
block_explorer_domain: getURLHostName(addressLink),
},
});
const isRemovable = keyring.type !== 'HD Key Tree';
return (
@ -55,7 +44,15 @@ export default function AccountOptionsMenu({ anchorElement, onClose }) {
>
<MenuItem
onClick={() => {
blockExplorerLinkClickedEvent();
trackEvent({
event: 'Clicked Block Explorer Link',
category: 'Navigation',
properties: {
link_type: 'Account Tracker',
action: 'Account Options',
block_explorer_domain: getURLHostName(addressLink),
},
});
global.platform.openTab({
url: addressLink,
});

View File

@ -10,7 +10,6 @@ import {
SEND_ROUTE,
BUILD_QUOTE_ROUTE,
} from '../../../helpers/constants/routes';
import { useNewMetricEvent } from '../../../hooks/useMetricEvent';
import Tooltip from '../../ui/tooltip';
import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display';
import { PRIMARY, SECONDARY } from '../../../helpers/constants/common';
@ -48,12 +47,6 @@ const EthOverview = ({ className }) => {
const isSwapsChain = useSelector(getIsSwapsChain);
const isBuyableChain = useSelector(getIsBuyableChain);
const primaryTokenImage = useSelector(getNativeCurrencyImage);
const enteredSwapsEvent = useNewMetricEvent({
event: 'Swaps Opened',
properties: { source: 'Main View', active_currency: 'ETH' },
category: 'swaps',
});
const defaultSwapsToken = useSelector(getSwapsDefaultToken);
return (
@ -138,7 +131,14 @@ const EthOverview = ({ className }) => {
Icon={SwapIcon}
onClick={() => {
if (isSwapsChain) {
enteredSwapsEvent();
trackEvent({
event: 'Swaps Opened',
category: 'swaps',
properties: {
source: 'Main View',
active_currency: 'ETH',
},
});
dispatch(setSwapsFromToken(defaultSwapsToken));
if (usingHardwareWallet) {
global.platform.openExtensionInBrowser(BUILD_QUOTE_ROUTE);

View File

@ -12,7 +12,6 @@ import {
SEND_ROUTE,
BUILD_QUOTE_ROUTE,
} from '../../../helpers/constants/routes';
import { useNewMetricEvent } from '../../../hooks/useMetricEvent';
import { useTokenTracker } from '../../../hooks/useTokenTracker';
import { useTokenFiatAmount } from '../../../hooks/useTokenFiatAmount';
import { updateSendAsset } from '../../../ducks/send';
@ -48,11 +47,6 @@ const TokenOverview = ({ className, token }) => {
token.symbol,
);
const isSwapsChain = useSelector(getIsSwapsChain);
const enteredSwapsEvent = useNewMetricEvent({
event: 'Swaps Opened',
properties: { source: 'Token View', active_currency: token.symbol },
category: 'swaps',
});
useEffect(() => {
if (token.isERC721 && process.env.COLLECTIBLES_V1) {
@ -121,7 +115,14 @@ const TokenOverview = ({ className, token }) => {
Icon={SwapIcon}
onClick={() => {
if (isSwapsChain) {
enteredSwapsEvent();
trackEvent({
event: 'Swaps Opened',
category: 'swaps',
properties: {
source: 'Token View',
active_currency: token.symbol,
},
});
dispatch(
setSwapsFromToken({
...token,

View File

@ -1,36 +1,7 @@
import { useContext, useCallback } from 'react';
import { useSelector } from 'react-redux';
import { useRouteMatch } from 'react-router-dom';
import { MetaMetricsContext as NewMetaMetricsContext } from '../contexts/metametrics.new';
import { PATH_NAME_MAP } from '../helpers/constants/routes';
import { txDataSelector } from '../selectors';
import { useEqualityCheck } from './useEqualityCheck';
// Type imports
/**
* @typedef {import('../contexts/metametrics.new').UIMetricsEventPayload} UIMetricsEventPayload
* @typedef {import('../../shared/constants/metametrics').MetaMetricsEventOptions} MetaMetricsEventOptions
*/
/**
* track a metametrics event using segment
* e.g metricsEvent({ event: 'Unlocked MetaMask', category: 'Navigation' })
*
* @param {UIMetricsEventPayload} payload - payload of the event to track
* @param {MetaMetricsEventOptions} options - options for handling/routing event
* @returns {() => Promise<void>} function to execute the tracking event
*/
export function useNewMetricEvent(payload, options) {
const memoizedPayload = useEqualityCheck(payload);
const memoizedOptions = useEqualityCheck(options);
const metricsEvent = useContext(NewMetaMetricsContext);
return useCallback(() => metricsEvent(memoizedPayload, memoizedOptions), [
metricsEvent,
memoizedPayload,
memoizedOptions,
]);
}
const PATHS_TO_CHECK = Object.keys(PATH_NAME_MAP);

View File

@ -1,4 +1,4 @@
import React from 'react';
import React, { useContext } from 'react';
import PropTypes from 'prop-types';
import { useSelector, useDispatch } from 'react-redux';
import { useHistory } from 'react-router-dom';
@ -14,7 +14,7 @@ import {
import { showModal } from '../../../store/actions';
import { DEFAULT_ROUTE } from '../../../helpers/constants/routes';
import { getURLHostName } from '../../../helpers/utils/util';
import { useNewMetricEvent } from '../../../hooks/useMetricEvent';
import { MetaMetricsContext } from '../../../contexts/metametrics.new';
import AssetNavigation from './asset-navigation';
import AssetOptions from './asset-options';
@ -29,16 +29,7 @@ export default function NativeAsset({ nativeCurrency }) {
const address = useSelector(getSelectedAddress);
const history = useHistory();
const accountLink = getAccountLink(address, chainId, rpcPrefs);
const blockExplorerLinkClickedEvent = useNewMetricEvent({
category: 'Navigation',
event: 'Clicked Block Explorer Link',
properties: {
link_type: 'Account Tracker',
action: 'Asset Options',
block_explorer_domain: getURLHostName(accountLink),
},
});
const trackEvent = useContext(MetaMetricsContext);
return (
<>
@ -51,7 +42,15 @@ export default function NativeAsset({ nativeCurrency }) {
<AssetOptions
isNativeAsset
onClickBlockExplorer={() => {
blockExplorerLinkClickedEvent();
trackEvent({
event: 'Clicked Block Explorer Link',
category: 'Navigation',
properties: {
link_type: 'Account Tracker',
action: 'Asset Options',
block_explorer_domain: getURLHostName(accountLink),
},
});
global.platform.openTab({
url: accountLink,
});

View File

@ -1,4 +1,4 @@
import React from 'react';
import React, { useContext } from 'react';
import PropTypes from 'prop-types';
import { useDispatch, useSelector } from 'react-redux';
import { useHistory } from 'react-router-dom';
@ -16,7 +16,7 @@ import {
} from '../../../helpers/constants/routes';
import { getURLHostName } from '../../../helpers/utils/util';
import { showModal } from '../../../store/actions';
import { useNewMetricEvent } from '../../../hooks/useMetricEvent';
import { MetaMetricsContext } from '../../../contexts/metametrics.new';
import AssetNavigation from './asset-navigation';
import AssetOptions from './asset-options';
@ -35,16 +35,7 @@ export default function TokenAsset({ token }) {
selectedAddress,
rpcPrefs,
);
const blockExplorerLinkClickedEvent = useNewMetricEvent({
category: 'Navigation',
event: 'Clicked Block Explorer Link',
properties: {
link_type: 'Token Tracker',
action: 'Token Options',
block_explorer_domain: getURLHostName(tokenTrackerLink),
},
});
const trackEvent = useContext(MetaMetricsContext);
return (
<>
@ -61,7 +52,15 @@ export default function TokenAsset({ token }) {
}
isEthNetwork={!rpcPrefs.blockExplorerUrl}
onClickBlockExplorer={() => {
blockExplorerLinkClickedEvent();
trackEvent({
event: 'Clicked Block Explorer Link',
category: 'Navigation',
properties: {
link_type: 'Token Tracker',
action: 'Token Options',
block_explorer_domain: getURLHostName(tokenTrackerLink),
},
});
global.platform.openTab({ url: tokenTrackerLink });
}}
onViewAccountDetails={() => {

View File

@ -1,9 +1,8 @@
import React, { useState, useMemo } from 'react';
import React, { useState, useMemo, useContext } from 'react';
import PropTypes from 'prop-types';
import { useHistory } from 'react-router-dom';
import zxcvbn from 'zxcvbn';
import { useSelector } from 'react-redux';
import { useNewMetricEvent } from '../../../hooks/useMetricEvent';
import { useI18nContext } from '../../../hooks/useI18nContext';
import Button from '../../../components/ui/button';
import Typography from '../../../components/ui/typography';
@ -30,6 +29,7 @@ import {
import ZENDESK_URLS from '../../../helpers/constants/zendesk-url';
import { getFirstTimeFlowType } from '../../../selectors';
import { FIRST_TIME_FLOW_TYPES } from '../../../helpers/constants/onboarding';
import { MetaMetricsContext } from '../../../contexts/metametrics.new';
export default function CreatePassword({
createNewAccount,
@ -47,11 +47,7 @@ export default function CreatePassword({
const [showPassword, setShowPassword] = useState(false);
const history = useHistory();
const firstTimeFlowType = useSelector(getFirstTimeFlowType);
const submitPasswordEvent = useNewMetricEvent({
event: 'Submit Password',
category: 'Onboarding',
});
const trackEvent = useContext(MetaMetricsContext);
const isValid = useMemo(() => {
if (!password || !confirmPassword || password !== confirmPassword) {
@ -142,7 +138,10 @@ export default function CreatePassword({
if (createNewAccount) {
await createNewAccount(password);
}
submitPasswordEvent();
trackEvent({
event: 'Submit Password',
category: 'Onboarding',
});
history.push(ONBOARDING_SECURE_YOUR_WALLET_ROUTE);
} catch (error) {
setPasswordError(error.message);

View File

@ -4,7 +4,6 @@ import { useHistory } from 'react-router-dom';
import isEqual from 'lodash/isEqual';
import { I18nContext } from '../../../contexts/i18n';
import { useNewMetricEvent } from '../../../hooks/useMetricEvent';
import {
getFetchParams,
getApproveTxParams,
@ -33,6 +32,7 @@ import {
DISPLAY,
} from '../../../helpers/constants/design-system';
import SwapsFooter from '../swaps-footer';
import { MetaMetricsContext } from '../../../contexts/metametrics.new';
import SwapStepIcon from './swap-step-icon';
export default function AwaitingSignatures() {
@ -52,28 +52,27 @@ export default function AwaitingSignatures() {
getCurrentSmartTransactionsEnabled,
);
const needsTwoConfirmations = Boolean(approveTxParams);
const awaitingSignaturesEvent = useNewMetricEvent({
event: 'Awaiting Signature(s) on a HW wallet',
sensitiveProperties: {
needs_two_confirmations: needsTwoConfirmations,
token_from: sourceTokenInfo?.symbol,
token_from_amount: fetchParams?.value,
token_to: destinationTokenInfo?.symbol,
request_type: fetchParams?.balanceError ? 'Quote' : 'Order',
slippage: fetchParams?.slippage,
custom_slippage: fetchParams?.slippage === 2,
is_hardware_wallet: hardwareWalletUsed,
hardware_wallet_type: hardwareWalletType,
stx_enabled: smartTransactionsEnabled,
current_stx_enabled: currentSmartTransactionsEnabled,
stx_user_opt_in: smartTransactionsOptInStatus,
},
category: 'swaps',
});
const trackEvent = useContext(MetaMetricsContext);
useEffect(() => {
awaitingSignaturesEvent();
trackEvent({
event: 'Awaiting Signature(s) on a HW wallet',
category: 'swaps',
sensitiveProperties: {
needs_two_confirmations: needsTwoConfirmations,
token_from: sourceTokenInfo?.symbol,
token_from_amount: fetchParams?.value,
token_to: destinationTokenInfo?.symbol,
request_type: fetchParams?.balanceError ? 'Quote' : 'Order',
slippage: fetchParams?.slippage,
custom_slippage: fetchParams?.slippage === 2,
is_hardware_wallet: hardwareWalletUsed,
hardware_wallet_type: hardwareWalletType,
stx_enabled: smartTransactionsEnabled,
current_stx_enabled: currentSmartTransactionsEnabled,
stx_user_opt_in: smartTransactionsOptInStatus,
},
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

View File

@ -7,7 +7,6 @@ import isEqual from 'lodash/isEqual';
import { getBlockExplorerLink } from '@metamask/etherscan-link';
import { I18nContext } from '../../../contexts/i18n';
import { SUPPORT_LINK } from '../../../helpers/constants/common';
import { useNewMetricEvent } from '../../../hooks/useMetricEvent';
import { MetaMetricsContext } from '../../../contexts/metametrics.new';
import {
@ -69,7 +68,7 @@ export default function AwaitingSwap({
submittingSwap,
}) {
const t = useContext(I18nContext);
const metaMetricsEvent = useContext(MetaMetricsContext);
const trackEvent = useContext(MetaMetricsContext);
const history = useHistory();
const dispatch = useDispatch();
const animationEventEmitter = useRef(new EventEmitter());
@ -131,16 +130,6 @@ export default function AwaitingSwap({
current_stx_enabled: currentSmartTransactionsEnabled,
stx_user_opt_in: smartTransactionsOptInStatus,
};
const quotesExpiredEvent = useNewMetricEvent({
event: 'Quotes Timed Out',
sensitiveProperties,
category: 'swaps',
});
const makeAnotherSwapEvent = useNewMetricEvent({
event: 'Make Another Swap',
sensitiveProperties,
category: 'swaps',
});
const baseNetworkUrl =
rpcPrefs.blockExplorerUrl ??
@ -197,7 +186,11 @@ export default function AwaitingSwap({
if (!trackedQuotesExpiredEvent) {
setTrackedQuotesExpiredEvent(true);
quotesExpiredEvent();
trackEvent({
event: 'Quotes Timed Out',
category: 'swaps',
sensitiveProperties,
});
}
} else if (errorKey === ERROR_FETCHING_QUOTES) {
headerText = t('swapFetchingQuotesErrorTitle');
@ -260,7 +253,11 @@ export default function AwaitingSwap({
<a
href="#"
onClick={async () => {
makeAnotherSwapEvent();
trackEvent({
event: 'Make Another Swap',
category: 'swaps',
sensitiveProperties,
});
await dispatch(navigateBackToBuildQuote(history));
dispatch(setSwapsFromToken(defaultSwapsToken));
}}
@ -306,7 +303,7 @@ export default function AwaitingSwap({
history,
fromTokenInputValue,
maxSlippage,
metaMetricsEvent,
trackEvent,
),
);
} else if (errorKey) {

View File

@ -2,8 +2,8 @@ import React, { useContext } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { I18nContext } from '../../../../contexts/i18n';
import { useNewMetricEvent } from '../../../../hooks/useMetricEvent';
import { getURLHostName } from '../../../../helpers/utils/util';
import { MetaMetricsContext } from '../../../../contexts/metametrics.new';
export default function ViewOnEtherScanLink({
txHash,
@ -11,16 +11,7 @@ export default function ViewOnEtherScanLink({
isCustomBlockExplorerUrl,
}) {
const t = useContext(I18nContext);
const blockExplorerLinkClickedEvent = useNewMetricEvent({
category: 'Swaps',
event: 'Clicked Block Explorer Link',
properties: {
link_type: 'Transaction Block Explorer',
action: 'Swap Transaction',
block_explorer_domain: getURLHostName(blockExplorerUrl),
},
});
const trackEvent = useContext(MetaMetricsContext);
return (
<div
@ -29,7 +20,15 @@ export default function ViewOnEtherScanLink({
'awaiting-swap__view-on-etherscan--invisible': !txHash,
})}
onClick={() => {
blockExplorerLinkClickedEvent();
trackEvent({
event: 'Clicked Block Explorer Link',
category: 'Swaps',
properties: {
link_type: 'Transaction Block Explorer',
action: 'Swap Transaction',
block_explorer_domain: getURLHostName(blockExplorerUrl),
},
});
global.platform.openTab({ url: blockExplorerUrl });
}}
>

View File

@ -7,7 +7,6 @@ import { uniqBy, isEqual } from 'lodash';
import { useHistory } from 'react-router-dom';
import { getTokenTrackerLink } from '@metamask/etherscan-link';
import { MetaMetricsContext } from '../../../contexts/metametrics.new';
import { useNewMetricEvent } from '../../../hooks/useMetricEvent';
import {
useTokensToSearch,
getRenderableTokenData,
@ -127,7 +126,7 @@ export default function BuildQuote({
const t = useContext(I18nContext);
const dispatch = useDispatch();
const history = useHistory();
const metaMetricsEvent = useContext(MetaMetricsContext);
const trackEvent = useContext(MetaMetricsContext);
const [fetchedTokenExchangeRate, setFetchedTokenExchangeRate] = useState(
undefined,
@ -346,16 +345,6 @@ export default function BuildQuote({
? getURLHostName(blockExplorerTokenLink)
: t('etherscan');
const blockExplorerLinkClickedEvent = useNewMetricEvent({
category: 'Swaps',
event: 'Clicked Block Explorer Link',
properties: {
link_type: 'Token Tracker',
action: 'Swaps Confirmation',
block_explorer_domain: getURLHostName(blockExplorerTokenLink),
},
});
const { destinationTokenAddedForSwap } = fetchParams || {};
const { address: toAddress } = toToken || {};
const onToSelect = useCallback(
@ -441,23 +430,32 @@ export default function BuildQuote({
fromTokenBalance,
]);
const buildQuotePageLoadedEvent = useNewMetricEvent({
event: 'Build Quote Page Loaded',
category: 'swaps',
sensitiveProperties: {
is_hardware_wallet: hardwareWalletUsed,
hardware_wallet_type: hardwareWalletType,
stx_enabled: smartTransactionsEnabled,
current_stx_enabled: currentSmartTransactionsEnabled,
stx_user_opt_in: smartTransactionsOptInStatus,
},
});
const trackBuildQuotePageLoadedEvent = useCallback(() => {
trackEvent({
event: 'Build Quote Page Loaded',
category: 'swaps',
sensitiveProperties: {
is_hardware_wallet: hardwareWalletUsed,
hardware_wallet_type: hardwareWalletType,
stx_enabled: smartTransactionsEnabled,
current_stx_enabled: currentSmartTransactionsEnabled,
stx_user_opt_in: smartTransactionsOptInStatus,
},
});
}, [
trackEvent,
hardwareWalletUsed,
hardwareWalletType,
smartTransactionsEnabled,
currentSmartTransactionsEnabled,
smartTransactionsOptInStatus,
]);
useEffect(() => {
dispatch(resetSwapsPostFetchState());
dispatch(setReviewSwapClickedTimestamp());
buildQuotePageLoadedEvent();
}, [dispatch, buildQuotePageLoadedEvent]);
trackBuildQuotePageLoadedEvent();
}, [dispatch, trackBuildQuotePageLoadedEvent]);
const BlockExplorerLink = () => {
return (
@ -465,7 +463,15 @@ export default function BuildQuote({
className="build-quote__token-etherscan-link build-quote__underline"
key="build-quote-etherscan-link"
onClick={() => {
blockExplorerLinkClickedEvent();
trackEvent({
event: 'Clicked Block Explorer Link',
category: 'Swaps',
properties: {
link_type: 'Token Tracker',
action: 'Swaps Confirmation',
block_explorer_domain: getURLHostName(blockExplorerTokenLink),
},
});
global.platform.openTab({
url: blockExplorerTokenLink,
});
@ -522,7 +528,7 @@ export default function BuildQuote({
history,
fromTokenInputValue,
maxSlippage,
metaMetricsEvent,
trackEvent,
pageRedirectionDisabled,
),
);
@ -541,7 +547,7 @@ export default function BuildQuote({
dispatch,
history,
maxSlippage,
metaMetricsEvent,
trackEvent,
isReviewSwapButtonDisabled,
fromTokenInputValue,
fromTokenAddress,
@ -786,7 +792,17 @@ export default function BuildQuote({
className="build-quote__token-etherscan-link"
key="build-quote-etherscan-link"
onClick={() => {
blockExplorerLinkClickedEvent();
trackEvent({
event: 'Clicked Block Explorer Link',
category: 'Swaps',
properties: {
link_type: 'Token Tracker',
action: 'Swaps Confirmation',
block_explorer_domain: getURLHostName(
blockExplorerTokenLink,
),
},
});
global.platform.openTab({
url: blockExplorerTokenLink,
});
@ -838,7 +854,7 @@ export default function BuildQuote({
history,
fromTokenInputValue,
maxSlippage,
metaMetricsEvent,
trackEvent,
),
);
} else if (areQuotesPresent) {

View File

@ -15,7 +15,6 @@ import PulseLoader from '../../../components/ui/pulse-loader';
import UrlIcon from '../../../components/ui/url-icon';
import ActionableMessage from '../../../components/ui/actionable-message/actionable-message';
import ImportToken from '../import-token';
import { useNewMetricEvent } from '../../../hooks/useMetricEvent';
import {
isHardwareWallet,
getHardwareWalletType,
@ -29,6 +28,7 @@ import {
getSmartTransactionsEnabled,
getCurrentSmartTransactionsEnabled,
} from '../../../ducks/swaps/swaps';
import { MetaMetricsContext } from '../../../contexts/metametrics.new';
export default function DropdownSearchList({
searchListClassName,
@ -68,20 +68,7 @@ export default function DropdownSearchList({
getCurrentSmartTransactionsEnabled,
);
const tokenImportedEvent = useNewMetricEvent({
event: 'Token Imported',
sensitiveProperties: {
symbol: tokenForImport?.symbol,
address: tokenForImport?.address,
chain_id: chainId,
is_hardware_wallet: hardwareWalletUsed,
hardware_wallet_type: hardwareWalletType,
stx_enabled: smartTransactionsEnabled,
current_stx_enabled: currentSmartTransactionsEnabled,
stx_user_opt_in: smartTransactionsOptInStatus,
},
category: 'swaps',
});
const trackEvent = useContext(MetaMetricsContext);
const close = useCallback(() => {
setIsOpen(false);
@ -103,7 +90,20 @@ export default function DropdownSearchList({
};
const onImportTokenClick = () => {
tokenImportedEvent();
trackEvent({
event: 'Token Imported',
category: 'swaps',
sensitiveProperties: {
symbol: tokenForImport?.symbol,
address: tokenForImport?.address,
chain_id: chainId,
is_hardware_wallet: hardwareWalletUsed,
hardware_wallet_type: hardwareWalletType,
stx_enabled: smartTransactionsEnabled,
current_stx_enabled: currentSmartTransactionsEnabled,
stx_user_opt_in: smartTransactionsOptInStatus,
},
});
// Only when a user confirms import of a token, we add it and show it in a dropdown.
onSelect?.(tokenForImport);
setSelectedItem(tokenForImport);
@ -157,16 +157,6 @@ export default function DropdownSearchList({
? getURLHostName(blockExplorerLink)
: t('etherscan');
const blockExplorerLinkClickedEvent = useNewMetricEvent({
category: 'Swaps',
event: 'Clicked Block Explorer Link',
properties: {
link_type: 'Token Tracker',
action: 'Verify Contract Address',
block_explorer_domain: getURLHostName(blockExplorerLink),
},
});
const importTokenProps = {
onImportTokenCloseClick,
onImportTokenClick,
@ -249,7 +239,17 @@ export default function DropdownSearchList({
<a
key="dropdown-search-list__etherscan-link"
onClick={() => {
blockExplorerLinkClickedEvent();
trackEvent({
event: 'Clicked Block Explorer Link',
category: 'Swaps',
properties: {
link_type: 'Token Tracker',
action: 'Verify Contract Address',
block_explorer_domain: getURLHostName(
blockExplorerLink,
),
},
});
global.platform.openTab({
url: blockExplorerLink,
});

View File

@ -2,7 +2,6 @@ import React, { useContext } from 'react';
import PropTypes from 'prop-types';
import { I18nContext } from '../../../contexts/i18n';
import InfoTooltip from '../../../components/ui/info-tooltip';
import { useNewMetricEvent } from '../../../hooks/useMetricEvent';
import {
MAINNET_CHAIN_ID,
BSC_CHAIN_ID,
@ -20,6 +19,7 @@ import {
FONT_WEIGHT,
} from '../../../helpers/constants/design-system';
import GasDetailsItemTitle from '../../../components/app/gas-details-item/gas-details-item-title';
import { MetaMetricsContext } from '../../../contexts/metametrics.new';
const GAS_FEES_LEARN_MORE_URL =
'https://community.metamask.io/t/what-is-gas-why-do-transactions-take-so-long/3172';
@ -60,11 +60,7 @@ export default function FeeCard({
throw new Error('This network is not supported for token swaps');
}
};
const gasFeesLearnMoreLinkClickedEvent = useNewMetricEvent({
category: 'Swaps',
event: 'Clicked "Gas Fees: Learn More" Link',
});
const trackEvent = useContext(MetaMetricsContext);
const tokenApprovalTextComponent = (
<span key="fee-card-approve-symbol" className="fee-card__bold">
@ -105,7 +101,10 @@ export default function FeeCard({
<a
className="fee-card__link"
onClick={() => {
gasFeesLearnMoreLinkClickedEvent();
trackEvent({
event: 'Clicked "Gas Fees: Learn More" Link',
category: 'Swaps',
});
global.platform.openTab({
url: GAS_FEES_LEARN_MORE_URL,
});

View File

@ -1,4 +1,10 @@
import React, { useEffect, useRef, useContext, useState } from 'react';
import React, {
useEffect,
useRef,
useContext,
useState,
useCallback,
} from 'react';
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
import {
Switch,
@ -75,11 +81,11 @@ import {
setSwapsErrorKey,
} from '../../store/actions';
import { useNewMetricEvent } from '../../hooks/useMetricEvent';
import { useGasFeeEstimates } from '../../hooks/useGasFeeEstimates';
import FeatureToggledRoute from '../../helpers/higher-order-components/feature-toggled-route';
import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction';
import ActionableMessage from '../../components/ui/actionable-message';
import { MetaMetricsContext } from '../../contexts/metametrics.new';
import {
fetchTokens,
fetchTopAssets,
@ -98,6 +104,7 @@ export default function Swap() {
const t = useContext(I18nContext);
const history = useHistory();
const dispatch = useDispatch();
const trackEvent = useContext(MetaMetricsContext);
const { pathname } = useLocation();
const isAwaitingSwapRoute = pathname === AWAITING_SWAP_ROUTE;
@ -236,28 +243,30 @@ export default function Swap() {
const hardwareWalletUsed = useSelector(isHardwareWallet);
const hardwareWalletType = useSelector(getHardwareWalletType);
const exitedSwapsEvent = useNewMetricEvent({
event: 'Exited Swaps',
category: 'swaps',
sensitiveProperties: {
token_from: fetchParams?.sourceTokenInfo?.symbol,
token_from_amount: fetchParams?.value,
request_type: fetchParams?.balanceError,
token_to: fetchParams?.destinationTokenInfo?.symbol,
slippage: fetchParams?.slippage,
custom_slippage: fetchParams?.slippage !== 2,
current_screen: pathname.match(/\/swaps\/(.+)/u)[1],
is_hardware_wallet: hardwareWalletUsed,
hardware_wallet_type: hardwareWalletType,
stx_enabled: smartTransactionsEnabled,
current_stx_enabled: currentSmartTransactionsEnabled,
stx_user_opt_in: smartTransactionsOptInStatus,
},
});
const trackExitedSwapsEvent = () => {
trackEvent({
event: 'Exited Swaps',
category: 'swaps',
sensitiveProperties: {
token_from: fetchParams?.sourceTokenInfo?.symbol,
token_from_amount: fetchParams?.value,
request_type: fetchParams?.balanceError,
token_to: fetchParams?.destinationTokenInfo?.symbol,
slippage: fetchParams?.slippage,
custom_slippage: fetchParams?.slippage !== 2,
current_screen: pathname.match(/\/swaps\/(.+)/u)[1],
is_hardware_wallet: hardwareWalletUsed,
hardware_wallet_type: hardwareWalletType,
stx_enabled: smartTransactionsEnabled,
current_stx_enabled: currentSmartTransactionsEnabled,
stx_user_opt_in: smartTransactionsOptInStatus,
},
});
};
const exitEventRef = useRef();
useEffect(() => {
exitEventRef.current = () => {
exitedSwapsEvent();
trackExitedSwapsEvent();
};
});
@ -295,31 +304,52 @@ export default function Swap() {
return () => window.removeEventListener('beforeunload', fn);
}, [dispatch, isLoadingQuotesRoute]);
const errorStxEvent = useNewMetricEvent({
event: 'Error Smart Transactions',
category: 'swaps',
sensitiveProperties: {
token_from: fetchParams?.sourceTokenInfo?.symbol,
token_from_amount: fetchParams?.value,
request_type: fetchParams?.balanceError,
token_to: fetchParams?.destinationTokenInfo?.symbol,
slippage: fetchParams?.slippage,
custom_slippage: fetchParams?.slippage !== 2,
current_screen: pathname.match(/\/swaps\/(.+)/u)[1],
is_hardware_wallet: hardwareWalletUsed,
hardware_wallet_type: hardwareWalletType,
stx_enabled: smartTransactionsEnabled,
current_stx_enabled: currentSmartTransactionsEnabled,
stx_user_opt_in: smartTransactionsOptInStatus,
stx_error: currentSmartTransactionsError,
},
});
const trackErrorStxEvent = useCallback(() => {
trackEvent({
event: 'Error Smart Transactions',
category: 'swaps',
sensitiveProperties: {
token_from: fetchParams?.sourceTokenInfo?.symbol,
token_from_amount: fetchParams?.value,
request_type: fetchParams?.balanceError,
token_to: fetchParams?.destinationTokenInfo?.symbol,
slippage: fetchParams?.slippage,
custom_slippage: fetchParams?.slippage !== 2,
current_screen: pathname.match(/\/swaps\/(.+)/u)[1],
is_hardware_wallet: hardwareWalletUsed,
hardware_wallet_type: hardwareWalletType,
stx_enabled: smartTransactionsEnabled,
current_stx_enabled: currentSmartTransactionsEnabled,
stx_user_opt_in: smartTransactionsOptInStatus,
stx_error: currentSmartTransactionsError,
},
});
}, [
currentSmartTransactionsError,
currentSmartTransactionsEnabled,
trackEvent,
fetchParams?.balanceError,
fetchParams?.destinationTokenInfo?.symbol,
fetchParams?.slippage,
fetchParams?.sourceTokenInfo?.symbol,
fetchParams?.value,
hardwareWalletType,
hardwareWalletUsed,
pathname,
smartTransactionsEnabled,
smartTransactionsOptInStatus,
]);
useEffect(() => {
if (currentSmartTransactionsError && !currentStxErrorTracked) {
setCurrentStxErrorTracked(true);
errorStxEvent();
trackErrorStxEvent();
}
}, [errorStxEvent, currentSmartTransactionsError, currentStxErrorTracked]);
}, [
currentSmartTransactionsError,
trackErrorStxEvent,
currentStxErrorTracked,
]);
if (!isSwapsChain) {
return <Redirect to={{ pathname: DEFAULT_ROUTE }} />;

View File

@ -12,8 +12,8 @@ import {
getRpcPrefsForCurrentProvider,
} from '../../../../selectors';
import { SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../../shared/constants/swaps';
import { useNewMetricEvent } from '../../../../hooks/useMetricEvent';
import { getURLHostName } from '../../../../helpers/utils/util';
import { MetaMetricsContext } from '../../../../contexts/metametrics.new';
export default function ItemList({
results = [],
@ -39,16 +39,7 @@ export default function ItemList({
const blockExplorerLabel = rpcPrefs.blockExplorerUrl
? getURLHostName(blockExplorerLink)
: t('etherscan');
const blockExplorerLinkClickedEvent = useNewMetricEvent({
category: 'Swaps',
event: 'Clicked Block Explorer Link',
properties: {
link_type: 'Token Tracker',
action: 'Verify Contract Address',
block_explorer_domain: getURLHostName(blockExplorerLink),
},
});
const trackEvent = useContext(MetaMetricsContext);
// If there is a token for import based on a contract address, it's the only one in the list.
const hasTokenForImport = results.length === 1 && results[0].notImported;
@ -162,7 +153,17 @@ export default function ItemList({
<a
key="searchable-item-list__etherscan-link"
onClick={() => {
blockExplorerLinkClickedEvent();
trackEvent({
event: 'Clicked Block Explorer Link',
category: 'Swaps',
properties: {
link_type: 'Token Tracker',
action: 'Verify Contract Address',
block_explorer_domain: getURLHostName(
blockExplorerLink,
),
},
});
global.platform.openTab({
url: blockExplorerLink,
});

View File

@ -3,7 +3,6 @@ import { useDispatch, useSelector } from 'react-redux';
import { useHistory } from 'react-router-dom';
import { I18nContext } from '../../../contexts/i18n';
import { useNewMetricEvent } from '../../../hooks/useMetricEvent';
import {
getFetchParams,
prepareToLeaveSwaps,
@ -45,6 +44,7 @@ import { SMART_TRANSACTION_STATUSES } from '../../../../shared/constants/transac
import SwapsFooter from '../swaps-footer';
import { calcTokenAmount } from '../../../helpers/utils/token-util';
import { showRemainingTimeInMinAndSec } from '../swaps.util';
import { MetaMetricsContext } from '../../../contexts/metametrics.new';
import SuccessIcon from './success-icon';
import RevertedIcon from './reverted-icon';
import CanceledIcon from './canceled-icon';
@ -114,18 +114,7 @@ export default function SmartTransactionStatus() {
destinationTokenInfo.decimals,
).toPrecision(8);
}
const stxStatusPageLoadedEvent = useNewMetricEvent({
event: 'STX Status Page Loaded',
category: 'swaps',
sensitiveProperties,
});
const cancelSmartTransactionEvent = useNewMetricEvent({
event: 'Cancel STX',
category: 'swaps',
sensitiveProperties,
});
const trackEvent = useContext(MetaMetricsContext);
const isSmartTransactionPending =
smartTransactionStatus === SMART_TRANSACTION_STATUSES.PENDING;
@ -134,7 +123,11 @@ export default function SmartTransactionStatus() {
smartTransactionStatus === SMART_TRANSACTION_STATUSES.SUCCESS;
useEffect(() => {
stxStatusPageLoadedEvent();
trackEvent({
event: 'STX Status Page Loaded',
category: 'swaps',
sensitiveProperties,
});
// eslint-disable-next-line
}, []);
@ -242,7 +235,11 @@ export default function SmartTransactionStatus() {
onClick={(e) => {
e?.preventDefault();
setCancelSwapLinkClicked(true); // We want to hide it after a user clicks on it.
cancelSmartTransactionEvent();
trackEvent({
event: 'Cancel STX',
category: 'swaps',
sensitiveProperties,
});
dispatch(cancelSwapsSmartTransaction(latestSmartTransactionUuid));
}}
>

View File

@ -1,4 +1,11 @@
import React, { useState, useContext, useMemo, useEffect, useRef } from 'react';
import React, {
useState,
useContext,
useMemo,
useEffect,
useRef,
useCallback,
} from 'react';
import { shallowEqual, useSelector, useDispatch } from 'react-redux';
import { useHistory } from 'react-router-dom';
import BigNumber from 'bignumber.js';
@ -8,7 +15,6 @@ import { I18nContext } from '../../../contexts/i18n';
import SelectQuotePopover from '../select-quote-popover';
import { useEthFiatAmount } from '../../../hooks/useEthFiatAmount';
import { useEqualityCheck } from '../../../hooks/useEqualityCheck';
import { useNewMetricEvent } from '../../../hooks/useMetricEvent';
import { usePrevious } from '../../../hooks/usePrevious';
import { useGasFeeInputs } from '../../../hooks/gasFeeInput/useGasFeeInputs';
import { MetaMetricsContext } from '../../../contexts/metametrics.new';
@ -121,7 +127,7 @@ export default function ViewQuote() {
const history = useHistory();
const dispatch = useDispatch();
const t = useContext(I18nContext);
const metaMetricsEvent = useContext(MetaMetricsContext);
const trackEvent = useContext(MetaMetricsContext);
const eip1559V2Enabled = useSelector(getEIP1559V2Enabled);
const [dispatchedSafeRefetch, setDispatchedSafeRefetch] = useState(false);
@ -495,76 +501,106 @@ export default function ViewQuote() {
const numberOfQuotes = Object.values(quotes).length;
const bestQuoteReviewedEventSent = useRef();
const eventObjectBase = {
token_from: sourceTokenSymbol,
token_from_amount: sourceTokenValue,
token_to: destinationTokenSymbol,
token_to_amount: destinationTokenValue,
request_type: fetchParams?.balanceError,
slippage: fetchParams?.slippage,
custom_slippage: fetchParams?.slippage !== 2,
response_time: fetchParams?.responseTime,
best_quote_source: topQuote?.aggregator,
available_quotes: numberOfQuotes,
is_hardware_wallet: hardwareWalletUsed,
hardware_wallet_type: hardwareWalletType,
stx_enabled: smartTransactionsEnabled,
current_stx_enabled: currentSmartTransactionsEnabled,
stx_user_opt_in: smartTransactionsOptInStatus,
const eventObjectBase = useMemo(() => {
return {
token_from: sourceTokenSymbol,
token_from_amount: sourceTokenValue,
token_to: destinationTokenSymbol,
token_to_amount: destinationTokenValue,
request_type: fetchParams?.balanceError,
slippage: fetchParams?.slippage,
custom_slippage: fetchParams?.slippage !== 2,
response_time: fetchParams?.responseTime,
best_quote_source: topQuote?.aggregator,
available_quotes: numberOfQuotes,
is_hardware_wallet: hardwareWalletUsed,
hardware_wallet_type: hardwareWalletType,
stx_enabled: smartTransactionsEnabled,
current_stx_enabled: currentSmartTransactionsEnabled,
stx_user_opt_in: smartTransactionsOptInStatus,
};
}, [
sourceTokenSymbol,
sourceTokenValue,
destinationTokenSymbol,
destinationTokenValue,
fetchParams?.balanceError,
fetchParams?.slippage,
fetchParams?.responseTime,
topQuote?.aggregator,
numberOfQuotes,
hardwareWalletUsed,
hardwareWalletType,
smartTransactionsEnabled,
currentSmartTransactionsEnabled,
smartTransactionsOptInStatus,
]);
const trackAllAvailableQuotesOpened = () => {
trackEvent({
event: 'All Available Quotes Opened',
category: 'swaps',
sensitiveProperties: {
...eventObjectBase,
other_quote_selected: usedQuote?.aggregator !== topQuote?.aggregator,
other_quote_selected_source:
usedQuote?.aggregator === topQuote?.aggregator
? null
: usedQuote?.aggregator,
},
});
};
const allAvailableQuotesOpened = useNewMetricEvent({
event: 'All Available Quotes Opened',
category: 'swaps',
sensitiveProperties: {
...eventObjectBase,
other_quote_selected: usedQuote?.aggregator !== topQuote?.aggregator,
other_quote_selected_source:
usedQuote?.aggregator === topQuote?.aggregator
? null
: usedQuote?.aggregator,
},
});
const quoteDetailsOpened = useNewMetricEvent({
event: 'Quote Details Opened',
category: 'swaps',
sensitiveProperties: {
...eventObjectBase,
other_quote_selected: usedQuote?.aggregator !== topQuote?.aggregator,
other_quote_selected_source:
usedQuote?.aggregator === topQuote?.aggregator
? null
: usedQuote?.aggregator,
},
});
const editSpendLimitOpened = useNewMetricEvent({
event: 'Edit Spend Limit Opened',
category: 'swaps',
sensitiveProperties: {
...eventObjectBase,
custom_spend_limit_set: originalApproveAmount === approveAmount,
custom_spend_limit_amount:
originalApproveAmount === approveAmount ? null : approveAmount,
},
});
const bestQuoteReviewedEvent = useNewMetricEvent({
event: 'Best Quote Reviewed',
category: 'swaps',
sensitiveProperties: {
...eventObjectBase,
network_fees: feeInFiat,
},
});
const viewQuotePageLoadedEvent = useNewMetricEvent({
event: 'View Quote Page Loaded',
category: 'swaps',
sensitiveProperties: {
...eventObjectBase,
response_time: currentTimestamp - reviewSwapClickedTimestamp,
},
});
const trackQuoteDetailsOpened = () => {
trackEvent({
event: 'Quote Details Opened',
category: 'swaps',
sensitiveProperties: {
...eventObjectBase,
other_quote_selected: usedQuote?.aggregator !== topQuote?.aggregator,
other_quote_selected_source:
usedQuote?.aggregator === topQuote?.aggregator
? null
: usedQuote?.aggregator,
},
});
};
const trackEditSpendLimitOpened = () => {
trackEvent({
event: 'Edit Spend Limit Opened',
category: 'swaps',
sensitiveProperties: {
...eventObjectBase,
custom_spend_limit_set: originalApproveAmount === approveAmount,
custom_spend_limit_amount:
originalApproveAmount === approveAmount ? null : approveAmount,
},
});
};
const trackBestQuoteReviewedEvent = useCallback(() => {
trackEvent({
event: 'Best Quote Reviewed',
category: 'swaps',
sensitiveProperties: {
...eventObjectBase,
network_fees: feeInFiat,
},
});
}, [trackEvent, eventObjectBase, feeInFiat]);
const trackViewQuotePageLoadedEvent = useCallback(() => {
trackEvent({
event: 'View Quote Page Loaded',
category: 'swaps',
sensitiveProperties: {
...eventObjectBase,
response_time: currentTimestamp - reviewSwapClickedTimestamp,
},
});
}, [
trackEvent,
eventObjectBase,
currentTimestamp,
reviewSwapClickedTimestamp,
]);
useEffect(() => {
if (
@ -581,24 +617,24 @@ export default function ViewQuote() {
].every((dep) => dep !== null && dep !== undefined)
) {
bestQuoteReviewedEventSent.current = true;
bestQuoteReviewedEvent();
trackBestQuoteReviewedEvent();
}
}, [
sourceTokenSymbol,
sourceTokenValue,
destinationTokenSymbol,
destinationTokenValue,
fetchParams,
topQuote,
numberOfQuotes,
feeInFiat,
bestQuoteReviewedEvent,
destinationTokenSymbol,
destinationTokenValue,
sourceTokenSymbol,
sourceTokenValue,
trackBestQuoteReviewedEvent,
]);
const metaMaskFee = usedQuote.fee;
const onFeeCardTokenApprovalClick = () => {
editSpendLimitOpened();
trackEditSpendLimitOpened();
dispatch(
showModal({
name: 'EDIT_APPROVAL_PERMISSION',
@ -827,9 +863,9 @@ export default function ViewQuote() {
// Thanks to the next line we will only do quotes polling 3 times before showing a Quote Timeout modal.
dispatch(setSwapsQuotesPollingLimitEnabled(true));
if (reviewSwapClickedTimestamp) {
viewQuotePageLoadedEvent();
trackViewQuotePageLoadedEvent();
}
}, [dispatch, viewQuotePageLoadedEvent, reviewSwapClickedTimestamp]);
}, [dispatch, trackViewQuotePageLoadedEvent, reviewSwapClickedTimestamp]);
useEffect(() => {
// if smart transaction error is turned off, reset submit clicked boolean
@ -877,7 +913,7 @@ export default function ViewQuote() {
onSubmit={(aggId) => dispatch(swapsQuoteSelected(aggId))}
swapToSymbol={destinationTokenSymbol}
initialAggId={usedQuote.aggregator}
onQuoteDetailsIsOpened={quoteDetailsOpened}
onQuoteDetailsIsOpened={trackQuoteDetailsOpened}
hideEstimatedGasFee={
smartTransactionsEnabled && smartTransactionsOptInStatus
}
@ -973,7 +1009,7 @@ export default function ViewQuote() {
metaMaskFee={String(metaMaskFee)}
numberOfQuotes={Object.values(quotes).length}
onQuotesClick={() => {
allAvailableQuotesOpened();
trackAllAvailableQuotesOpened();
setSelectQuotePopoverShown(true);
}}
chainId={chainId}
@ -1002,7 +1038,7 @@ export default function ViewQuote() {
dispatch(
signAndSendSwapsSmartTransaction({
unsignedTransaction,
metaMetricsEvent,
trackEvent,
history,
additionalTrackingParams,
}),
@ -1011,7 +1047,7 @@ export default function ViewQuote() {
dispatch(
signAndSendTransactions(
history,
metaMetricsEvent,
trackEvent,
additionalTrackingParams,
),
);