mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 01:47:00 +01:00
UX: Multichain: Analytics (#18674)
This commit is contained in:
parent
bbb35dbe8d
commit
e339afce7a
@ -458,6 +458,7 @@ export enum MetaMetricsEventName {
|
||||
AppInstalled = 'App Installed',
|
||||
AppUnlocked = 'App Unlocked',
|
||||
AppUnlockedFailed = 'App Unlocked Failed',
|
||||
AppLocked = 'App Locked',
|
||||
AppWindowExpanded = 'App Window Expanded',
|
||||
BridgeLinkClicked = 'Bridge Link Clicked',
|
||||
DecryptionApproved = 'Decryption Approved',
|
||||
@ -541,6 +542,17 @@ export enum MetaMetricsEventName {
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
UserClickedDeepLink = 'User clicked deeplink',
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
AccountDetailMenuOpened = 'Account Details Menu Opened',
|
||||
BlockExplorerLinkClicked = 'Block Explorer Clicked',
|
||||
AccountRemoved = 'Account Removed',
|
||||
TestNetworksDisplayed = 'Test Networks Displayed',
|
||||
AddNetworkButtonClick = 'Add Network Button Clicked',
|
||||
CustomNetworkAdded = 'Custom Network Added',
|
||||
TokenDetailsOpened = 'Token Details Opened',
|
||||
NftScreenOpened = 'NFT Screen Opened',
|
||||
ActivityScreenOpened = 'Activity Screen Opened',
|
||||
WhatsNewViewed = `What's New Viewed`,
|
||||
WhatsNewClicked = `What's New Link Clicked`,
|
||||
}
|
||||
|
||||
export enum MetaMetricsEventAccountType {
|
||||
@ -583,6 +595,7 @@ export enum MetaMetricsEventCategory {
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
MMI = 'Institutional',
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
Tokens = 'Tokens',
|
||||
}
|
||||
|
||||
export enum MetaMetricsEventLinkType {
|
||||
|
@ -34,7 +34,7 @@ describe('Portfolio site', function () {
|
||||
// Verify site
|
||||
assert.equal(
|
||||
await driver.getCurrentUrl(),
|
||||
'http://127.0.0.1:8080/?metamaskEntry=ext',
|
||||
'http://127.0.0.1:8080/?metamaskEntry=ext&metametricsId=null',
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -6,7 +6,10 @@ import classNames from 'classnames';
|
||||
import Box from '../../../ui/box/box';
|
||||
import Button from '../../../ui/button';
|
||||
import { useI18nContext } from '../../../../hooks/useI18nContext';
|
||||
import { getDetectedTokensInCurrentNetwork } from '../../../../selectors';
|
||||
import {
|
||||
getCurrentChainId,
|
||||
getDetectedTokensInCurrentNetwork,
|
||||
} from '../../../../selectors';
|
||||
import { MetaMetricsContext } from '../../../../contexts/metametrics';
|
||||
import {
|
||||
MetaMetricsEventCategory,
|
||||
@ -23,13 +26,16 @@ const DetectedTokensLink = ({ className = '', setShowDetectedTokens }) => {
|
||||
({ address, symbol }) => `${symbol} - ${address}`,
|
||||
);
|
||||
|
||||
const chainId = useSelector(getCurrentChainId);
|
||||
|
||||
const onClick = () => {
|
||||
setShowDetectedTokens(true);
|
||||
trackEvent({
|
||||
event: MetaMetricsEventName.TokenImportClicked,
|
||||
category: MetaMetricsEventCategory.Wallet,
|
||||
properties: {
|
||||
source: MetaMetricsTokenEventSource.Detected,
|
||||
source_connection_method: MetaMetricsTokenEventSource.Detected,
|
||||
chain_id: chainId,
|
||||
tokens: detectedTokensDetails,
|
||||
},
|
||||
});
|
||||
|
@ -12,6 +12,7 @@ import { TypographyVariant } from '../../../../helpers/constants/design-system';
|
||||
|
||||
import SecurityProviderBannerMessage from '../../security-provider-banner-message/security-provider-banner-message';
|
||||
import { SECURITY_PROVIDER_MESSAGE_SEVERITIES } from '../../security-provider-banner-message/security-provider-banner-message.constants';
|
||||
import { getPortfolioUrl } from '../../../../helpers/utils/portfolio';
|
||||
import { ConfirmPageContainerSummary, ConfirmPageContainerWarning } from '.';
|
||||
|
||||
export default class ConfirmPageContainerContent extends Component {
|
||||
@ -54,6 +55,7 @@ export default class ConfirmPageContainerContent extends Component {
|
||||
transactionType: PropTypes.string,
|
||||
isBuyableChain: PropTypes.bool,
|
||||
txData: PropTypes.object,
|
||||
metaMetricsId: PropTypes.string,
|
||||
};
|
||||
|
||||
renderContent() {
|
||||
@ -159,6 +161,7 @@ export default class ConfirmPageContainerContent extends Component {
|
||||
transactionType,
|
||||
isBuyableChain,
|
||||
txData,
|
||||
metaMetricsId,
|
||||
} = this.props;
|
||||
|
||||
const { t } = this.context;
|
||||
@ -222,9 +225,12 @@ export default class ConfirmPageContainerContent extends Component {
|
||||
type="inline"
|
||||
className="confirm-page-container-content__link"
|
||||
onClick={() => {
|
||||
const portfolioUrl = process.env.PORTFOLIO_URL;
|
||||
global.platform.openTab({
|
||||
url: `${portfolioUrl}/buy?metamaskEntry=ext_buy_button`,
|
||||
url: getPortfolioUrl(
|
||||
'buy',
|
||||
'ext_buy_button',
|
||||
metaMetricsId,
|
||||
),
|
||||
});
|
||||
}}
|
||||
key={`${nativeCurrency}-buy-button`}
|
||||
|
@ -39,6 +39,7 @@ import {
|
||||
getIsBuyableChain,
|
||||
getMetadataContractName,
|
||||
getMetaMaskIdentities,
|
||||
getMetaMetricsId,
|
||||
getNetworkIdentifier,
|
||||
getSwapsDefaultToken,
|
||||
} from '../../../selectors';
|
||||
@ -116,6 +117,8 @@ const ConfirmPageContainer = (props) => {
|
||||
getMetadataContractName(state, toAddress),
|
||||
);
|
||||
|
||||
const metaMetricsId = useSelector(getMetaMetricsId);
|
||||
|
||||
// TODO: Move useRamps hook to the confirm-transaction-base parent component.
|
||||
// TODO: openBuyCryptoInPdapp should be passed to this component as a custom prop.
|
||||
// We try to keep this component for layout purpose only, we need to move this hook to the confirm-transaction-base parent
|
||||
@ -198,6 +201,7 @@ const ConfirmPageContainer = (props) => {
|
||||
)}
|
||||
{contentComponent || (
|
||||
<ConfirmPageContainerContent
|
||||
metaMetricsId={metaMetricsId}
|
||||
action={action}
|
||||
title={title}
|
||||
image={image}
|
||||
|
@ -9,7 +9,10 @@ import {
|
||||
MetaMetricsEventName,
|
||||
MetaMetricsTokenEventSource,
|
||||
} from '../../../../../shared/constants/metametrics';
|
||||
import { getDetectedTokensInCurrentNetwork } from '../../../../selectors';
|
||||
import {
|
||||
getCurrentChainId,
|
||||
getDetectedTokensInCurrentNetwork,
|
||||
} from '../../../../selectors';
|
||||
|
||||
import Popover from '../../../ui/popover';
|
||||
import Box from '../../../ui/box';
|
||||
@ -27,6 +30,8 @@ const DetectedTokenSelectionPopover = ({
|
||||
const t = useI18nContext();
|
||||
const trackEvent = useContext(MetaMetricsContext);
|
||||
|
||||
const chainId = useSelector(getCurrentChainId);
|
||||
|
||||
const detectedTokens = useSelector(getDetectedTokensInCurrentNetwork);
|
||||
const { selected: selectedTokens = [] } =
|
||||
sortingBasedOnTokenSelection(tokensListDetected);
|
||||
@ -44,7 +49,8 @@ const DetectedTokenSelectionPopover = ({
|
||||
event: MetaMetricsEventName.TokenImportCanceled,
|
||||
category: MetaMetricsEventCategory.Wallet,
|
||||
properties: {
|
||||
source: MetaMetricsTokenEventSource.Detected,
|
||||
source_connection_method: MetaMetricsTokenEventSource.Detected,
|
||||
chain_id: chainId,
|
||||
tokens: eventTokensDetails,
|
||||
},
|
||||
});
|
||||
|
@ -8,7 +8,10 @@ import {
|
||||
ignoreTokens,
|
||||
setNewTokensImported,
|
||||
} from '../../../store/actions';
|
||||
import { getDetectedTokensInCurrentNetwork } from '../../../selectors';
|
||||
import {
|
||||
getCurrentChainId,
|
||||
getDetectedTokensInCurrentNetwork,
|
||||
} from '../../../selectors';
|
||||
import { MetaMetricsContext } from '../../../contexts/metametrics';
|
||||
|
||||
import {
|
||||
@ -47,6 +50,7 @@ const DetectedToken = ({ setShowDetectedTokens }) => {
|
||||
const dispatch = useDispatch();
|
||||
const trackEvent = useContext(MetaMetricsContext);
|
||||
|
||||
const chainId = useSelector(getCurrentChainId);
|
||||
const detectedTokens = useSelector(getDetectedTokensInCurrentNetwork);
|
||||
|
||||
const [tokensListDetected, setTokensListDetected] = useState(() =>
|
||||
@ -69,9 +73,11 @@ const DetectedToken = ({ setShowDetectedTokens }) => {
|
||||
token_symbol: importedToken.symbol,
|
||||
token_contract_address: importedToken.address,
|
||||
token_decimal_precision: importedToken.decimals,
|
||||
source: MetaMetricsTokenEventSource.Detected,
|
||||
source_connection_method: MetaMetricsTokenEventSource.Detected,
|
||||
token_standard: TokenStandard.ERC20,
|
||||
asset_type: AssetType.token,
|
||||
token_added_type: 'detected',
|
||||
chain_id: chainId,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
@ -30,6 +30,8 @@ import {
|
||||
getIsBuyableChain,
|
||||
getNativeCurrencyImage,
|
||||
getSelectedAccountCachedBalance,
|
||||
getCurrentChainId,
|
||||
getMetaMetricsId,
|
||||
} from '../../../selectors';
|
||||
import { setSwapsFromToken } from '../../../ducks/swaps/swaps';
|
||||
import IconButton from '../../ui/icon-button';
|
||||
@ -52,6 +54,7 @@ import {
|
||||
} from '../../component-library';
|
||||
import { IconColor } from '../../../helpers/constants/design-system';
|
||||
import useRamps from '../../../hooks/experiences/useRamps';
|
||||
import { getPortfolioUrl } from '../../../helpers/utils/portfolio';
|
||||
import WalletOverview from './wallet-overview';
|
||||
|
||||
const EthOverview = ({ className }) => {
|
||||
@ -70,6 +73,8 @@ const EthOverview = ({ className }) => {
|
||||
const isBuyableChain = useSelector(getIsBuyableChain);
|
||||
const primaryTokenImage = useSelector(getNativeCurrencyImage);
|
||||
const defaultSwapsToken = useSelector(getSwapsDefaultToken);
|
||||
const chainId = useSelector(getCurrentChainId);
|
||||
const metaMetricsId = useSelector(getMetaMetricsId);
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
const mmiPortfolioEnabled = useSelector(getMmiPortfolioEnabled);
|
||||
@ -166,9 +171,13 @@ const EthOverview = ({ className }) => {
|
||||
ariaLabel={t('portfolio')}
|
||||
size={ButtonIconSize.Lg}
|
||||
onClick={() => {
|
||||
const portfolioUrl = process.env.PORTFOLIO_URL;
|
||||
const portfolioUrl = getPortfolioUrl(
|
||||
'',
|
||||
'ext',
|
||||
metaMetricsId,
|
||||
);
|
||||
global.platform.openTab({
|
||||
url: `${portfolioUrl}?metamaskEntry=ext`,
|
||||
url: portfolioUrl,
|
||||
});
|
||||
trackEvent(
|
||||
{
|
||||
@ -226,6 +235,8 @@ const EthOverview = ({ className }) => {
|
||||
properties: {
|
||||
location: 'Home',
|
||||
text: 'Buy',
|
||||
chain_id: chainId,
|
||||
token_symbol: defaultSwapsToken,
|
||||
},
|
||||
});
|
||||
}}
|
||||
@ -257,6 +268,7 @@ const EthOverview = ({ className }) => {
|
||||
token_symbol: 'ETH',
|
||||
location: 'Home',
|
||||
text: 'Send',
|
||||
chain_id: chainId,
|
||||
},
|
||||
});
|
||||
dispatch(
|
||||
@ -284,6 +296,7 @@ const EthOverview = ({ className }) => {
|
||||
token_symbol: 'ETH',
|
||||
location: MetaMetricsSwapsEventSource.MainView,
|
||||
text: 'Swap',
|
||||
chain_id: chainId,
|
||||
},
|
||||
});
|
||||
dispatch(setSwapsFromToken(defaultSwapsToken));
|
||||
@ -320,10 +333,13 @@ const EthOverview = ({ className }) => {
|
||||
label={t('bridge')}
|
||||
onClick={() => {
|
||||
if (isBridgeChain) {
|
||||
const portfolioUrl = process.env.PORTFOLIO_URL;
|
||||
const bridgeUrl = `${portfolioUrl}/bridge`;
|
||||
const portfolioUrl = getPortfolioUrl(
|
||||
'bridge',
|
||||
'ext_bridge_button',
|
||||
metaMetricsId,
|
||||
);
|
||||
global.platform.openTab({
|
||||
url: `${bridgeUrl}?metamaskEntry=ext_bridge_button${
|
||||
url: `${portfolioUrl}${
|
||||
location.pathname.includes('asset') ? '&token=native' : ''
|
||||
}`,
|
||||
});
|
||||
@ -333,6 +349,8 @@ const EthOverview = ({ className }) => {
|
||||
properties: {
|
||||
location: 'Home',
|
||||
text: 'Bridge',
|
||||
chain_id: chainId,
|
||||
token_symbol: 'ETH',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -20,6 +20,8 @@ import {
|
||||
getIsSwapsChain,
|
||||
getIsBuyableChain,
|
||||
getIsBridgeToken,
|
||||
getCurrentChainId,
|
||||
getMetaMetricsId,
|
||||
} from '../../../selectors';
|
||||
|
||||
import IconButton from '../../ui/icon-button';
|
||||
@ -39,6 +41,7 @@ import { ButtonIcon, Icon, IconName } from '../../component-library';
|
||||
import { IconColor } from '../../../helpers/constants/design-system';
|
||||
|
||||
import { BUTTON_ICON_SIZES } from '../../component-library/button-icon/deprecated';
|
||||
import { getPortfolioUrl } from '../../../helpers/utils/portfolio';
|
||||
import WalletOverview from './wallet-overview';
|
||||
|
||||
const TokenOverview = ({ className, token }) => {
|
||||
@ -56,9 +59,11 @@ const TokenOverview = ({ className, token }) => {
|
||||
balanceToRender,
|
||||
token.symbol,
|
||||
);
|
||||
const chainId = useSelector(getCurrentChainId);
|
||||
const isSwapsChain = useSelector(getIsSwapsChain);
|
||||
const isBridgeToken = useSelector(getIsBridgeToken(token.address));
|
||||
const isBuyableChain = useSelector(getIsBuyableChain);
|
||||
const metaMetricsId = useSelector(getMetaMetricsId);
|
||||
|
||||
const { openBuyCryptoInPdapp } = useRamps();
|
||||
|
||||
@ -92,9 +97,9 @@ const TokenOverview = ({ className, token }) => {
|
||||
ariaLabel={t('portfolio')}
|
||||
size={BUTTON_ICON_SIZES.LG}
|
||||
onClick={() => {
|
||||
const portfolioUrl = process.env.PORTFOLIO_URL;
|
||||
const portfolioUrl = getPortfolioUrl('', 'ext', metaMetricsId);
|
||||
global.platform.openTab({
|
||||
url: `${portfolioUrl}?metamaskEntry=ext`,
|
||||
url: portfolioUrl,
|
||||
});
|
||||
trackEvent(
|
||||
{
|
||||
@ -137,6 +142,8 @@ const TokenOverview = ({ className, token }) => {
|
||||
properties: {
|
||||
location: 'Token Overview',
|
||||
text: 'Buy',
|
||||
chain_id: chainId,
|
||||
token_symbol: token.symbol,
|
||||
},
|
||||
});
|
||||
}}
|
||||
@ -152,6 +159,7 @@ const TokenOverview = ({ className, token }) => {
|
||||
token_symbol: token.symbol,
|
||||
location: MetaMetricsSwapsEventSource.TokenView,
|
||||
text: 'Send',
|
||||
chain_id: chainId,
|
||||
},
|
||||
});
|
||||
try {
|
||||
@ -195,6 +203,7 @@ const TokenOverview = ({ className, token }) => {
|
||||
token_symbol: token.symbol,
|
||||
location: MetaMetricsSwapsEventSource.TokenView,
|
||||
text: 'Swap',
|
||||
chain_id: chainId,
|
||||
},
|
||||
});
|
||||
dispatch(
|
||||
@ -225,11 +234,13 @@ const TokenOverview = ({ className, token }) => {
|
||||
}
|
||||
label={t('bridge')}
|
||||
onClick={() => {
|
||||
const portfolioUrl = process.env.PORTFOLIO_URL;
|
||||
|
||||
const bridgeUrl = `${portfolioUrl}/bridge`;
|
||||
const portfolioUrl = getPortfolioUrl(
|
||||
'bridge',
|
||||
'ext_bridge_button',
|
||||
metaMetricsId,
|
||||
);
|
||||
global.platform.openTab({
|
||||
url: `${bridgeUrl}?metamaskEntry=ext_bridge_button&token=${token.address}`,
|
||||
url: `${portfolioUrl}&token=${token.address}`,
|
||||
});
|
||||
trackEvent({
|
||||
category: MetaMetricsEventCategory.Navigation,
|
||||
@ -237,6 +248,9 @@ const TokenOverview = ({ className, token }) => {
|
||||
properties: {
|
||||
location: 'Token Overview',
|
||||
text: 'Bridge',
|
||||
url: portfolioUrl,
|
||||
chain_id: chainId,
|
||||
token_symbol: token.symbol,
|
||||
},
|
||||
});
|
||||
}}
|
||||
|
@ -307,7 +307,7 @@ describe('TokenOverview', () => {
|
||||
await waitFor(() =>
|
||||
expect(openTabSpy).toHaveBeenCalledWith({
|
||||
url: expect.stringContaining(
|
||||
'/bridge?metamaskEntry=ext_bridge_button&token=0x7ceb23fd6bc0add59e62ac25578270cff1B9f619',
|
||||
'/bridge?metamaskEntry=ext_bridge_button&metametricsId=&token=0x7ceb23fd6bc0add59e62ac25578270cff1B9f619',
|
||||
),
|
||||
}),
|
||||
);
|
||||
|
@ -20,6 +20,11 @@ import {
|
||||
} from '../../../helpers/constants/routes';
|
||||
import { TextVariant } from '../../../helpers/constants/design-system';
|
||||
import ZENDESK_URLS from '../../../helpers/constants/zendesk-url';
|
||||
import { MetaMetricsContext } from '../../../contexts/metametrics';
|
||||
import {
|
||||
MetaMetricsEventCategory,
|
||||
MetaMetricsEventName,
|
||||
} from '../../../../shared/constants/metametrics';
|
||||
|
||||
function getActionFunctionById(id, history) {
|
||||
const actionFunctions = {
|
||||
@ -107,9 +112,16 @@ const renderDescription = (description) => {
|
||||
);
|
||||
};
|
||||
|
||||
const renderFirstNotification = (notification, idRefMap, history, isLast) => {
|
||||
const renderFirstNotification = (
|
||||
notification,
|
||||
idRefMap,
|
||||
history,
|
||||
isLast,
|
||||
trackEvent,
|
||||
) => {
|
||||
const { id, date, title, description, image, actionText } = notification;
|
||||
const actionFunction = getActionFunctionById(id, history);
|
||||
|
||||
const imageComponent = image && (
|
||||
<img
|
||||
className="whats-new-popup__notification-image"
|
||||
@ -144,7 +156,13 @@ const renderFirstNotification = (notification, idRefMap, history, isLast) => {
|
||||
<Button
|
||||
type="primary"
|
||||
className="whats-new-popup__button"
|
||||
onClick={actionFunction}
|
||||
onClick={() => {
|
||||
actionFunction();
|
||||
trackEvent({
|
||||
category: MetaMetricsEventCategory.Home,
|
||||
event: MetaMetricsEventName.WhatsNewClicked,
|
||||
});
|
||||
}}
|
||||
>
|
||||
{actionText}
|
||||
</Button>
|
||||
@ -218,6 +236,8 @@ export default function WhatsNewPopup({ onClose }) {
|
||||
[memoizedNotifications],
|
||||
);
|
||||
|
||||
const trackEvent = useContext(MetaMetricsContext);
|
||||
|
||||
const handleScrollDownClick = (e) => {
|
||||
e.stopPropagation();
|
||||
idRefMap[notifications[notifications.length - 1].id].current.scrollIntoView(
|
||||
@ -267,6 +287,14 @@ export default function WhatsNewPopup({ onClose }) {
|
||||
className="whats-new-popup__popover"
|
||||
onClose={() => {
|
||||
updateViewedNotifications(seenNotifications);
|
||||
trackEvent({
|
||||
category: MetaMetricsEventCategory.Home,
|
||||
event: MetaMetricsEventName.WhatsNewViewed,
|
||||
properties: {
|
||||
number_viewed: Object.keys(seenNotifications).pop(),
|
||||
completed_all: true,
|
||||
},
|
||||
});
|
||||
onClose();
|
||||
}}
|
||||
popoverRef={popoverRef}
|
||||
@ -280,7 +308,13 @@ export default function WhatsNewPopup({ onClose }) {
|
||||
// Display the swaps notification with full image
|
||||
// Displays the NFTs & OpenSea notifications 18,19 with full image
|
||||
return index === 0 || id === 1 || id === 18 || id === 19
|
||||
? renderFirstNotification(notification, idRefMap, history, isLast)
|
||||
? renderFirstNotification(
|
||||
notification,
|
||||
idRefMap,
|
||||
history,
|
||||
isLast,
|
||||
trackEvent,
|
||||
)
|
||||
: renderSubsequentNotification(
|
||||
notification,
|
||||
idRefMap,
|
||||
|
@ -9,7 +9,10 @@ import {
|
||||
getRpcPrefsForCurrentProvider,
|
||||
getBlockExplorerLinkText,
|
||||
getCurrentChainId,
|
||||
getHardwareWalletType,
|
||||
getAccountTypeForKeyring,
|
||||
} from '../../../selectors';
|
||||
import { findKeyringForAddress } from '../../../ducks/metamask/metamask';
|
||||
import { NETWORKS_ROUTE } from '../../../helpers/constants/routes';
|
||||
import { Menu, MenuItem } from '../../ui/menu';
|
||||
import { Text, IconName } from '../../component-library';
|
||||
@ -21,6 +24,7 @@ import {
|
||||
import { getURLHostName } from '../../../helpers/utils/util';
|
||||
import { showModal } from '../../../store/actions';
|
||||
import { TextVariant } from '../../../helpers/constants/design-system';
|
||||
import { formatAccountType } from '../../../helpers/utils/metrics';
|
||||
|
||||
export const AccountListItemMenu = ({
|
||||
anchorElement,
|
||||
@ -39,6 +43,13 @@ export const AccountListItemMenu = ({
|
||||
const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider);
|
||||
const addressLink = getAccountLink(identity.address, chainId, rpcPrefs);
|
||||
|
||||
const deviceName = useSelector(getHardwareWalletType);
|
||||
|
||||
const keyring = useSelector((state) =>
|
||||
findKeyringForAddress(state, identity.address),
|
||||
);
|
||||
const accountType = formatAccountType(getAccountTypeForKeyring(keyring));
|
||||
|
||||
const blockExplorerLinkText = useSelector(getBlockExplorerLinkText);
|
||||
const openBlockExplorer = () => {
|
||||
trackEvent({
|
||||
@ -50,6 +61,7 @@ export const AccountListItemMenu = ({
|
||||
url_domain: getURLHostName(addressLink),
|
||||
},
|
||||
});
|
||||
|
||||
global.platform.openTab({
|
||||
url: addressLink,
|
||||
});
|
||||
@ -67,11 +79,20 @@ export const AccountListItemMenu = ({
|
||||
onHide={onClose}
|
||||
>
|
||||
<MenuItem
|
||||
onClick={
|
||||
onClick={() => {
|
||||
blockExplorerLinkText.firstPart === 'addBlockExplorer'
|
||||
? routeToAddBlockExplorerUrl
|
||||
: openBlockExplorer
|
||||
}
|
||||
? routeToAddBlockExplorerUrl()
|
||||
: openBlockExplorer();
|
||||
|
||||
trackEvent({
|
||||
event: MetaMetricsEventName.BlockExplorerLinkClicked,
|
||||
category: MetaMetricsEventCategory.Accounts,
|
||||
properties: {
|
||||
location: 'Account Options',
|
||||
chain_id: chainId,
|
||||
},
|
||||
});
|
||||
}}
|
||||
subtitle={blockExplorerUrlSubTitle || null}
|
||||
iconName={IconName.Export}
|
||||
data-testid="account-list-menu-open-explorer"
|
||||
@ -105,6 +126,15 @@ export const AccountListItemMenu = ({
|
||||
identity,
|
||||
}),
|
||||
);
|
||||
trackEvent({
|
||||
event: MetaMetricsEventName.AccountRemoved,
|
||||
category: MetaMetricsEventCategory.Accounts,
|
||||
properties: {
|
||||
account_hardware_type: deviceName,
|
||||
chain_id: chainId,
|
||||
account_type: accountType,
|
||||
},
|
||||
});
|
||||
onClose();
|
||||
}}
|
||||
iconName={IconName.Trash}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useState, useRef } from 'react';
|
||||
import React, { useState, useRef, useContext } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
|
||||
@ -38,6 +38,11 @@ import UserPreferencedCurrencyDisplay from '../../app/user-preferenced-currency-
|
||||
import { SECONDARY, PRIMARY } from '../../../helpers/constants/common';
|
||||
import { findKeyringForAddress } from '../../../ducks/metamask/metamask';
|
||||
import Tooltip from '../../ui/tooltip/tooltip';
|
||||
import {
|
||||
MetaMetricsEventCategory,
|
||||
MetaMetricsEventName,
|
||||
} from '../../../../shared/constants/metametrics';
|
||||
import { MetaMetricsContext } from '../../../contexts/metametrics';
|
||||
|
||||
const MAXIMUM_CURRENCY_DECIMALS = 3;
|
||||
const MAXIMUM_CHARACTERS_WITHOUT_TOOLTIP = 17;
|
||||
@ -82,6 +87,8 @@ export const AccountListItem = ({
|
||||
const { blockExplorerUrl } = rpcPrefs;
|
||||
const blockExplorerUrlSubTitle = getURLHostName(blockExplorerUrl);
|
||||
|
||||
const trackEvent = useContext(MetaMetricsContext);
|
||||
|
||||
return (
|
||||
<Box
|
||||
display={DISPLAY.FLEX}
|
||||
@ -207,6 +214,13 @@ export const AccountListItem = ({
|
||||
size={IconSize.Sm}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
trackEvent({
|
||||
event: MetaMetricsEventName.AccountDetailMenuOpened,
|
||||
category: MetaMetricsEventCategory.Navigation,
|
||||
properties: {
|
||||
location: 'Account Options',
|
||||
},
|
||||
});
|
||||
setAccountOptionsMenuOpen(true);
|
||||
}}
|
||||
data-testid="account-list-item-menu-button"
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useContext, useState, useRef } from 'react';
|
||||
import React, { useContext, useState, useRef, useCallback } from 'react';
|
||||
import classnames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import browser from 'webextension-polyfill';
|
||||
@ -30,6 +30,7 @@ import {
|
||||
} from '../../component-library';
|
||||
|
||||
import {
|
||||
getCurrentChainId,
|
||||
getCurrentNetwork,
|
||||
getOnboardedInThisUISession,
|
||||
getOriginOfCurrentTab,
|
||||
@ -60,6 +61,7 @@ export const AppHeader = ({ onClick }) => {
|
||||
const history = useHistory();
|
||||
const isUnlocked = useSelector((state) => state.metamask.isUnlocked);
|
||||
const t = useI18nContext();
|
||||
const chainId = useSelector(getCurrentChainId);
|
||||
|
||||
// Used for account picker
|
||||
const identity = useSelector(getSelectedIdentity);
|
||||
@ -71,7 +73,7 @@ export const AppHeader = ({ onClick }) => {
|
||||
// Used for network icon / dropdown
|
||||
const currentNetwork = useSelector(getCurrentNetwork);
|
||||
|
||||
// used to get the environment and connection status
|
||||
// Used to get the environment and connection status
|
||||
const popupStatus = getEnvironmentType() === ENVIRONMENT_TYPE_POPUP;
|
||||
const showStatus =
|
||||
getEnvironmentType() === ENVIRONMENT_TYPE_POPUP &&
|
||||
@ -83,6 +85,19 @@ export const AppHeader = ({ onClick }) => {
|
||||
.querySelector('[dir]')
|
||||
?.getAttribute('dir');
|
||||
|
||||
// Callback for network dropdown
|
||||
const networkOpenCallback = useCallback(() => {
|
||||
dispatch(toggleNetworkMenu());
|
||||
trackEvent({
|
||||
event: MetaMetricsEventName.NavNetworkMenuOpened,
|
||||
category: MetaMetricsEventCategory.Navigation,
|
||||
properties: {
|
||||
location: 'App header',
|
||||
chain_id: chainId,
|
||||
},
|
||||
});
|
||||
}, [chainId, dispatch, trackEvent]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{isUnlocked && !popupStatus ? (
|
||||
@ -140,14 +155,14 @@ export const AppHeader = ({ onClick }) => {
|
||||
name={currentNetwork?.nickname}
|
||||
src={currentNetwork?.rpcPrefs?.imageUrl}
|
||||
size={Size.SM}
|
||||
onClick={() => dispatch(toggleNetworkMenu())}
|
||||
onClick={networkOpenCallback}
|
||||
display={[DISPLAY.FLEX, DISPLAY.NONE]} // show on popover hide on desktop
|
||||
/>
|
||||
<PickerNetwork
|
||||
margin={2}
|
||||
label={currentNetwork?.nickname}
|
||||
src={currentNetwork?.rpcPrefs?.imageUrl}
|
||||
onClick={() => dispatch(toggleNetworkMenu())}
|
||||
onClick={networkOpenCallback}
|
||||
display={[DISPLAY.NONE, DISPLAY.FLEX]} // show on desktop hide on popover
|
||||
/>
|
||||
{showProductTour &&
|
||||
@ -171,7 +186,17 @@ export const AppHeader = ({ onClick }) => {
|
||||
<AccountPicker
|
||||
address={identity.address}
|
||||
name={identity.name}
|
||||
onClick={() => dispatch(toggleAccountMenu())}
|
||||
onClick={() => {
|
||||
dispatch(toggleAccountMenu());
|
||||
|
||||
trackEvent({
|
||||
event: MetaMetricsEventName.NavAccountMenuOpened,
|
||||
category: MetaMetricsEventCategory.Navigation,
|
||||
properties: {
|
||||
location: 'Home',
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Box
|
||||
display={DISPLAY.FLEX}
|
||||
@ -181,7 +206,13 @@ export const AppHeader = ({ onClick }) => {
|
||||
{showStatus ? (
|
||||
<Box ref={menuRef}>
|
||||
<ConnectedStatusIndicator
|
||||
onClick={() => history.push(CONNECTED_ACCOUNTS_ROUTE)}
|
||||
onClick={() => {
|
||||
history.push(CONNECTED_ACCOUNTS_ROUTE);
|
||||
trackEvent({
|
||||
event: MetaMetricsEventName.NavConnectedSitesOpened,
|
||||
category: MetaMetricsEventCategory.Navigation,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
) : null}{' '}
|
||||
|
@ -4,7 +4,10 @@ import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { useI18nContext } from '../../../hooks/useI18nContext';
|
||||
import { getDetectedTokensInCurrentNetwork } from '../../../selectors';
|
||||
import {
|
||||
getCurrentChainId,
|
||||
getDetectedTokensInCurrentNetwork,
|
||||
} from '../../../selectors';
|
||||
import { MetaMetricsContext } from '../../../contexts/metametrics';
|
||||
import {
|
||||
MetaMetricsEventCategory,
|
||||
@ -26,14 +29,17 @@ export const DetectedTokensBanner = ({
|
||||
({ address, symbol }) => `${symbol} - ${address}`,
|
||||
);
|
||||
|
||||
const chainId = useSelector(getCurrentChainId);
|
||||
|
||||
const handleOnClick = () => {
|
||||
actionButtonOnClick();
|
||||
trackEvent({
|
||||
event: MetaMetricsEventName.TokenImportClicked,
|
||||
category: MetaMetricsEventCategory.Wallet,
|
||||
properties: {
|
||||
source: MetaMetricsTokenEventSource.Detected,
|
||||
source_connection_method: MetaMetricsTokenEventSource.Detected,
|
||||
tokens: detectedTokensDetails,
|
||||
chain_id: chainId,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useContext } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import {
|
||||
CONNECTED_ROUTE,
|
||||
SETTINGS_ROUTE,
|
||||
@ -21,12 +21,15 @@ import {
|
||||
MetaMetricsEventCategory,
|
||||
MetaMetricsContextProp,
|
||||
} from '../../../../shared/constants/metametrics';
|
||||
import { getPortfolioUrl } from '../../../helpers/utils/portfolio';
|
||||
import { getMetaMetricsId } from '../../../selectors';
|
||||
|
||||
export const GlobalMenu = ({ closeMenu, anchorElement }) => {
|
||||
const t = useI18nContext();
|
||||
const dispatch = useDispatch();
|
||||
const trackEvent = useContext(MetaMetricsContext);
|
||||
const history = useHistory();
|
||||
const metaMetricsId = useSelector(getMetaMetricsId);
|
||||
|
||||
return (
|
||||
<Menu anchorElement={anchorElement} onHide={closeMenu}>
|
||||
@ -38,7 +41,7 @@ export const GlobalMenu = ({ closeMenu, anchorElement }) => {
|
||||
event: MetaMetricsEventName.NavConnectedSitesOpened,
|
||||
category: MetaMetricsEventCategory.Navigation,
|
||||
properties: {
|
||||
location: 'Account Options',
|
||||
location: 'Global Menu',
|
||||
},
|
||||
});
|
||||
closeMenu();
|
||||
@ -49,9 +52,9 @@ export const GlobalMenu = ({ closeMenu, anchorElement }) => {
|
||||
<MenuItem
|
||||
iconName={IconName.Diagram}
|
||||
onClick={() => {
|
||||
const portfolioUrl = process.env.PORTFOLIO_URL;
|
||||
const portfolioUrl = getPortfolioUrl('', 'ext', metaMetricsId);
|
||||
global.platform.openTab({
|
||||
url: `${portfolioUrl}?metamaskEntry=ext`,
|
||||
url: portfolioUrl,
|
||||
});
|
||||
trackEvent(
|
||||
{
|
||||
@ -59,6 +62,7 @@ export const GlobalMenu = ({ closeMenu, anchorElement }) => {
|
||||
event: MetaMetricsEventName.PortfolioLinkClicked,
|
||||
properties: {
|
||||
url: portfolioUrl,
|
||||
location: 'Global Menu',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -82,7 +86,7 @@ export const GlobalMenu = ({ closeMenu, anchorElement }) => {
|
||||
event: MetaMetricsEventName.AppWindowExpanded,
|
||||
category: MetaMetricsEventCategory.Navigation,
|
||||
properties: {
|
||||
location: 'Account Options',
|
||||
location: 'Global Menu',
|
||||
},
|
||||
});
|
||||
closeMenu();
|
||||
@ -102,6 +106,7 @@ export const GlobalMenu = ({ closeMenu, anchorElement }) => {
|
||||
event: MetaMetricsEventName.SupportLinkClicked,
|
||||
properties: {
|
||||
url: SUPPORT_LINK,
|
||||
location: 'Global Menu',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -124,7 +129,7 @@ export const GlobalMenu = ({ closeMenu, anchorElement }) => {
|
||||
category: MetaMetricsEventCategory.Navigation,
|
||||
event: MetaMetricsEventName.NavSettingsOpened,
|
||||
properties: {
|
||||
location: 'Main Menu',
|
||||
location: 'Global Menu',
|
||||
},
|
||||
});
|
||||
closeMenu();
|
||||
@ -137,6 +142,13 @@ export const GlobalMenu = ({ closeMenu, anchorElement }) => {
|
||||
onClick={() => {
|
||||
dispatch(lockMetamask());
|
||||
history.push(DEFAULT_ROUTE);
|
||||
trackEvent({
|
||||
category: MetaMetricsEventCategory.Navigation,
|
||||
event: MetaMetricsEventName.AppLocked,
|
||||
properties: {
|
||||
location: 'Global Menu',
|
||||
},
|
||||
});
|
||||
closeMenu();
|
||||
}}
|
||||
data-testid="global-menu-lock"
|
||||
|
@ -38,7 +38,7 @@ describe('AccountListItem', () => {
|
||||
fireEvent.click(getByTestId('global-menu-portfolio'));
|
||||
await waitFor(() => {
|
||||
expect(global.platform.openTab).toHaveBeenCalledWith({
|
||||
url: `${process.env.PORTFOLIO_URL}?metamaskEntry=ext`,
|
||||
url: `/?metamaskEntry=ext&metametricsId=`,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useContext } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useSelector } from 'react-redux';
|
||||
import classnames from 'classnames';
|
||||
@ -21,9 +21,14 @@ import {
|
||||
Text,
|
||||
} from '../../component-library';
|
||||
import Box from '../../ui/box/box';
|
||||
import { getNativeCurrencyImage } from '../../../selectors';
|
||||
import { getCurrentChainId, getNativeCurrencyImage } from '../../../selectors';
|
||||
import Tooltip from '../../ui/tooltip';
|
||||
import { useI18nContext } from '../../../hooks/useI18nContext';
|
||||
import { MetaMetricsContext } from '../../../contexts/metametrics';
|
||||
import {
|
||||
MetaMetricsEventCategory,
|
||||
MetaMetricsEventName,
|
||||
} from '../../../../shared/constants/metametrics';
|
||||
|
||||
export const MultichainTokenListItem = ({
|
||||
className,
|
||||
@ -37,6 +42,9 @@ export const MultichainTokenListItem = ({
|
||||
const t = useI18nContext();
|
||||
const primaryTokenImage = useSelector(getNativeCurrencyImage);
|
||||
const dataTheme = document.documentElement.getAttribute('data-theme');
|
||||
const trackEvent = useContext(MetaMetricsContext);
|
||||
const chainId = useSelector(getCurrentChainId);
|
||||
|
||||
return (
|
||||
<Box
|
||||
className={classnames('multichain-token-list-item', className)}
|
||||
@ -56,6 +64,15 @@ export const MultichainTokenListItem = ({
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
onClick();
|
||||
trackEvent({
|
||||
category: MetaMetricsEventCategory.Tokens,
|
||||
event: MetaMetricsEventName.TokenDetailsOpened,
|
||||
properties: {
|
||||
location: 'Home',
|
||||
chain_id: chainId,
|
||||
token_symbol: tokenSymbol,
|
||||
},
|
||||
});
|
||||
}}
|
||||
>
|
||||
<BadgeWrapper
|
||||
|
@ -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';
|
||||
@ -28,6 +28,11 @@ import { Button, BUTTON_VARIANT, Text } from '../../component-library';
|
||||
import { ADD_POPULAR_CUSTOM_NETWORK } from '../../../helpers/constants/routes';
|
||||
import { getEnvironmentType } from '../../../../app/scripts/lib/util';
|
||||
import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../shared/constants/app';
|
||||
import { MetaMetricsContext } from '../../../contexts/metametrics';
|
||||
import {
|
||||
MetaMetricsEventCategory,
|
||||
MetaMetricsEventName,
|
||||
} from '../../../../shared/constants/metametrics';
|
||||
|
||||
const UNREMOVABLE_CHAIN_IDS = [CHAIN_IDS.MAINNET, ...TEST_CHAINS];
|
||||
|
||||
@ -38,6 +43,7 @@ export const NetworkListMenu = ({ onClose }) => {
|
||||
const currentChainId = useSelector(getCurrentChainId);
|
||||
const dispatch = useDispatch();
|
||||
const history = useHistory();
|
||||
const trackEvent = useContext(MetaMetricsContext);
|
||||
|
||||
const environmentType = getEnvironmentType();
|
||||
const isFullScreen = environmentType === ENVIRONMENT_TYPE_FULLSCREEN;
|
||||
@ -65,6 +71,16 @@ export const NetworkListMenu = ({ onClose }) => {
|
||||
} else {
|
||||
dispatch(setActiveNetwork(network.id));
|
||||
}
|
||||
trackEvent({
|
||||
event: MetaMetricsEventName.NavNetworkSwitched,
|
||||
category: MetaMetricsEventCategory.Network,
|
||||
properties: {
|
||||
location: 'Network Menu',
|
||||
chain_id: currentChainId,
|
||||
from_network: currentChainId,
|
||||
to_network: network.id || network.chainId,
|
||||
},
|
||||
});
|
||||
}}
|
||||
onDeleteClick={
|
||||
canDeleteNetwork
|
||||
@ -92,7 +108,16 @@ export const NetworkListMenu = ({ onClose }) => {
|
||||
<Text>{t('showTestnetNetworks')}</Text>
|
||||
<ToggleButton
|
||||
value={showTestNetworks}
|
||||
onToggle={(value) => dispatch(setShowTestNetworks(!value))}
|
||||
onToggle={(value) => {
|
||||
const shouldShowTestNetworks = !value;
|
||||
dispatch(setShowTestNetworks(shouldShowTestNetworks));
|
||||
if (shouldShowTestNetworks) {
|
||||
trackEvent({
|
||||
event: MetaMetricsEventName.TestNetworksDisplayed,
|
||||
category: MetaMetricsEventCategory.Network,
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Box padding={4}>
|
||||
@ -106,6 +131,10 @@ export const NetworkListMenu = ({ onClose }) => {
|
||||
ADD_POPULAR_CUSTOM_NETWORK,
|
||||
);
|
||||
dispatch(toggleNetworkMenu());
|
||||
trackEvent({
|
||||
event: MetaMetricsEventName.AddNetworkButtonClick,
|
||||
category: MetaMetricsEventCategory.Network,
|
||||
});
|
||||
}}
|
||||
>
|
||||
{t('addNetwork')}
|
||||
|
@ -8,3 +8,11 @@ export function getMethodName(camelCase) {
|
||||
.replace(/([A-Z])([a-z])/gu, ' $1$2')
|
||||
.replace(/ +/gu, ' ');
|
||||
}
|
||||
|
||||
export function formatAccountType(accountType) {
|
||||
if (accountType === 'default') {
|
||||
return 'metamask';
|
||||
}
|
||||
|
||||
return accountType;
|
||||
}
|
||||
|
8
ui/helpers/utils/portfolio.js
Normal file
8
ui/helpers/utils/portfolio.js
Normal file
@ -0,0 +1,8 @@
|
||||
export function getPortfolioUrl(
|
||||
endpoint = '',
|
||||
metamaskEntry = '',
|
||||
metaMetricsId = '',
|
||||
) {
|
||||
const portfolioUrl = process.env.PORTFOLIO_URL || '';
|
||||
return `${portfolioUrl}/${endpoint}?metamaskEntry=${metamaskEntry}&metametricsId=${metaMetricsId}`;
|
||||
}
|
@ -112,7 +112,7 @@ export default function AddNft() {
|
||||
tokenId: tokenId.toString(),
|
||||
asset_type: AssetType.NFT,
|
||||
token_standard: tokenDetails?.standard,
|
||||
source: MetaMetricsTokenEventSource.Custom,
|
||||
source_connection_method: MetaMetricsTokenEventSource.Custom,
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -129,7 +129,7 @@ const ConfirmAddSuggestedToken = () => {
|
||||
token_contract_address: asset.address,
|
||||
token_decimal_precision: asset.decimals,
|
||||
unlisted: asset.unlisted,
|
||||
source: MetaMetricsTokenEventSource.Dapp,
|
||||
source_connection_method: MetaMetricsTokenEventSource.Dapp,
|
||||
token_standard: TokenStandard.ERC20,
|
||||
asset_type: AssetType.token,
|
||||
},
|
||||
|
@ -51,7 +51,7 @@ const ConfirmImportToken = () => {
|
||||
token_contract_address: pendingToken.address,
|
||||
token_decimal_precision: pendingToken.decimals,
|
||||
unlisted: pendingToken.unlisted,
|
||||
source: pendingToken.isCustom
|
||||
source_connection_method: pendingToken.isCustom
|
||||
? MetaMetricsTokenEventSource.Custom
|
||||
: MetaMetricsTokenEventSource.List,
|
||||
token_standard: TokenStandard.ERC20,
|
||||
|
@ -48,10 +48,12 @@ export default function NewAccountImportForm() {
|
||||
navigateToMostRecentOverviewPage();
|
||||
} else {
|
||||
dispatch(actions.displayWarning(t('importAccountError')));
|
||||
trackImportEvent(strategy, false);
|
||||
}
|
||||
})
|
||||
.catch((error) => translateWarning(error.message));
|
||||
.catch((error) => {
|
||||
trackImportEvent(strategy, error.message);
|
||||
translateWarning(error.message);
|
||||
});
|
||||
}
|
||||
|
||||
function trackImportEvent(strategy, wasSuccessful) {
|
||||
|
@ -35,6 +35,7 @@ export default class NewAccountCreateForm extends Component {
|
||||
event: MetaMetricsEventName.AccountAdded,
|
||||
properties: {
|
||||
account_type: MetaMetricsEventAccountType.Default,
|
||||
location: 'Home',
|
||||
},
|
||||
});
|
||||
history.push(mostRecentOverviewPage);
|
||||
|
@ -674,7 +674,24 @@ export default class Home extends PureComponent {
|
||||
<Tabs
|
||||
t={this.context.t}
|
||||
defaultActiveTabKey={defaultHomeActiveTabName}
|
||||
onTabClick={onTabClick}
|
||||
onTabClick={(tabName) => {
|
||||
onTabClick(tabName);
|
||||
let event;
|
||||
switch (tabName) {
|
||||
case 'nfts':
|
||||
event = MetaMetricsEventName.NftScreenOpened;
|
||||
break;
|
||||
case 'activity':
|
||||
event = MetaMetricsEventName.ActivityScreenOpened;
|
||||
break;
|
||||
default:
|
||||
event = MetaMetricsEventName.TokenScreenOpened;
|
||||
}
|
||||
this.context.trackEvent({
|
||||
category: MetaMetricsEventCategory.Home,
|
||||
event,
|
||||
});
|
||||
}}
|
||||
tabsClassName="home__tabs"
|
||||
>
|
||||
<Tab
|
||||
|
@ -1,4 +1,10 @@
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import React, {
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import validUrl from 'valid-url';
|
||||
@ -23,12 +29,17 @@ import {
|
||||
} from '../../../../store/actions';
|
||||
import fetchWithCache from '../../../../../shared/lib/fetch-with-cache';
|
||||
import { usePrevious } from '../../../../hooks/usePrevious';
|
||||
import { MetaMetricsNetworkEventSource } from '../../../../../shared/constants/metametrics';
|
||||
import {
|
||||
MetaMetricsEventCategory,
|
||||
MetaMetricsEventName,
|
||||
MetaMetricsNetworkEventSource,
|
||||
} from '../../../../../shared/constants/metametrics';
|
||||
import {
|
||||
infuraProjectId,
|
||||
FEATURED_RPCS,
|
||||
} from '../../../../../shared/constants/network';
|
||||
import { decimalToHex } from '../../../../../shared/modules/conversion.utils';
|
||||
import { MetaMetricsContext } from '../../../../contexts/metametrics';
|
||||
|
||||
/**
|
||||
* Attempts to convert the given chainId to a decimal string, for display
|
||||
@ -96,6 +107,8 @@ const NetworksForm = ({
|
||||
const [isEditing, setIsEditing] = useState(Boolean(addNewNetwork));
|
||||
const [previousNetwork, setPreviousNetwork] = useState(selectedNetwork);
|
||||
|
||||
const trackEvent = useContext(MetaMetricsContext);
|
||||
|
||||
const resetForm = useCallback(() => {
|
||||
setNetworkName(selectedNetworkName || '');
|
||||
setRpcUrl(selectedNetwork.rpcUrl);
|
||||
@ -543,6 +556,19 @@ const NetworksForm = ({
|
||||
}),
|
||||
);
|
||||
|
||||
trackEvent({
|
||||
event: MetaMetricsEventName.CustomNetworkAdded,
|
||||
category: MetaMetricsEventCategory.Network,
|
||||
properties: {
|
||||
block_explorer_url: blockExplorerUrl,
|
||||
chain_id: prefixedChainId,
|
||||
network_name: networkName,
|
||||
source_connection_method:
|
||||
MetaMetricsNetworkEventSource.CustomNetworkForm,
|
||||
token_symbol: ticker,
|
||||
},
|
||||
});
|
||||
|
||||
submitCallback?.();
|
||||
}
|
||||
} catch (error) {
|
||||
|
@ -119,6 +119,11 @@ export function getCurrentChainId(state) {
|
||||
return chainId;
|
||||
}
|
||||
|
||||
export function getMetaMetricsId(state) {
|
||||
const { metaMetricsId } = state.metamask;
|
||||
return metaMetricsId;
|
||||
}
|
||||
|
||||
export function isCurrentProviderCustom(state) {
|
||||
const provider = getProvider(state);
|
||||
return (
|
||||
@ -233,7 +238,15 @@ export function getHardwareWalletType(state) {
|
||||
|
||||
export function getAccountType(state) {
|
||||
const currentKeyring = getCurrentKeyring(state);
|
||||
const type = currentKeyring && currentKeyring.type;
|
||||
return getAccountTypeForKeyring(currentKeyring);
|
||||
}
|
||||
|
||||
export function getAccountTypeForKeyring(keyring) {
|
||||
if (!keyring) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const { type } = keyring;
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
if (type.startsWith('Custody')) {
|
||||
@ -245,6 +258,7 @@ export function getAccountType(state) {
|
||||
case KeyringType.trezor:
|
||||
case KeyringType.ledger:
|
||||
case KeyringType.lattice:
|
||||
case KeyringType.qr:
|
||||
return 'hardware';
|
||||
case KeyringType.imported:
|
||||
return 'imported';
|
||||
|
Loading…
Reference in New Issue
Block a user