1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-26 20:39:08 +01:00
metamask-extension/ui/pages/add-collectible/add-collectible.js
Elliot Winkler 51cffa15dd
Migrate to new controller packages (#16547)
* Migrate to new controller packages

`@metamask/controllers` is deprecated, and most of the controllers that
lived here are now located in their own package ([1]). This commit
replaces `@metamask/controllers` in `package.json` with references to
these packages and updates `import` lines to match.

[1]: https://github.com/MetaMask/controllers/pull/831

* Support GitHub registry for draft PRs (#16549)

* Add additional allowed host to lockfile linter

* Update LavaMoat policies

* Add policy exception for nanoid

* Add additional nanoid overrides

* Update LavaMoat policies again

* Bump controller packages

* Update lavamoat

* Bump controller packages

* Update packages to v1.0.0

* Expand gitignore comment

* Unpin controller dependencies, using ^ range instead

Co-authored-by: Mark Stacey <markjstacey@gmail.com>
2022-11-24 16:29:07 -03:30

180 lines
5.7 KiB
JavaScript

import React, { useContext, useState } from 'react';
import { useHistory } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import { isValidHexAddress } from '@metamask/controller-utils';
import { useI18nContext } from '../../hooks/useI18nContext';
import { DEFAULT_ROUTE } from '../../helpers/constants/routes';
import {
DISPLAY,
FONT_WEIGHT,
TYPOGRAPHY,
} from '../../helpers/constants/design-system';
import Box from '../../components/ui/box';
import Typography from '../../components/ui/typography';
import ActionableMessage from '../../components/ui/actionable-message';
import PageContainer from '../../components/ui/page-container';
import {
addNftVerifyOwnership,
getTokenStandardAndDetails,
ignoreTokens,
setNewCollectibleAddedMessage,
} from '../../store/actions';
import FormField from '../../components/ui/form-field';
import { getIsMainnet, getUseNftDetection } from '../../selectors';
import { getCollectiblesDetectionNoticeDismissed } from '../../ducks/metamask/metamask';
import CollectiblesDetectionNotice from '../../components/app/collectibles-detection-notice';
import { MetaMetricsContext } from '../../contexts/metametrics';
import { ASSET_TYPES } from '../../../shared/constants/transaction';
import { EVENT, EVENT_NAMES } from '../../../shared/constants/metametrics';
export default function AddCollectible() {
const t = useI18nContext();
const history = useHistory();
const dispatch = useDispatch();
const useNftDetection = useSelector(getUseNftDetection);
const isMainnet = useSelector(getIsMainnet);
const collectibleDetectionNoticeDismissed = useSelector(
getCollectiblesDetectionNoticeDismissed,
);
const addressEnteredOnImportTokensPage =
history?.location?.state?.addressEnteredOnImportTokensPage;
const contractAddressToConvertFromTokenToCollectible =
history?.location?.state?.tokenAddress;
const [address, setAddress] = useState(
addressEnteredOnImportTokensPage ??
contractAddressToConvertFromTokenToCollectible ??
'',
);
const [tokenId, setTokenId] = useState('');
const [disabled, setDisabled] = useState(true);
const [collectibleAddFailed, setCollectibleAddFailed] = useState(false);
const trackEvent = useContext(MetaMetricsContext);
const handleAddCollectible = async () => {
try {
await dispatch(addNftVerifyOwnership(address, tokenId));
} catch (error) {
const { message } = error;
dispatch(setNewCollectibleAddedMessage(message));
setCollectibleAddFailed(true);
return;
}
if (contractAddressToConvertFromTokenToCollectible) {
await dispatch(
ignoreTokens({
tokensToIgnore: contractAddressToConvertFromTokenToCollectible,
dontShowLoadingIndicator: true,
}),
);
}
dispatch(setNewCollectibleAddedMessage('success'));
const tokenDetails = await getTokenStandardAndDetails(
address,
null,
tokenId.toString(),
);
trackEvent({
event: EVENT_NAMES.TOKEN_ADDED,
category: 'Wallet',
sensitiveProperties: {
token_contract_address: address,
token_symbol: tokenDetails?.symbol,
tokenId: tokenId.toString(),
asset_type: ASSET_TYPES.NFT,
token_standard: tokenDetails?.standard,
source: EVENT.SOURCE.TOKEN.CUSTOM,
},
});
history.push(DEFAULT_ROUTE);
};
const validateAndSetAddress = (val) => {
setDisabled(!isValidHexAddress(val) || !tokenId);
setAddress(val);
};
const validateAndSetTokenId = (val) => {
setDisabled(!isValidHexAddress(address) || !val || isNaN(Number(val)));
setTokenId(val);
};
return (
<PageContainer
title={t('importNFT')}
onSubmit={() => {
handleAddCollectible();
}}
submitText={t('add')}
onCancel={() => {
history.push(DEFAULT_ROUTE);
}}
onClose={() => {
history.push(DEFAULT_ROUTE);
}}
disabled={disabled}
contentComponent={
<Box>
{isMainnet &&
!useNftDetection &&
!collectibleDetectionNoticeDismissed ? (
<CollectiblesDetectionNotice />
) : null}
{collectibleAddFailed && (
<ActionableMessage
type="danger"
useIcon
iconFillColor="var(--color-error-default)"
message={
<Box display={DISPLAY.INLINE_FLEX}>
<Typography
variant={TYPOGRAPHY.H7}
fontWeight={FONT_WEIGHT.NORMAL}
margin={0}
>
{t('collectibleAddFailedMessage')}
</Typography>
<button
className="fas fa-times add-collectible__close"
title={t('close')}
onClick={() => setCollectibleAddFailed(false)}
/>
</Box>
}
/>
)}
<Box margin={4}>
<FormField
dataTestId="address"
titleText={t('address')}
placeholder="0x..."
value={address}
onChange={(val) => {
validateAndSetAddress(val);
setCollectibleAddFailed(false);
}}
tooltipText={t('importNFTAddressToolTip')}
autoFocus
/>
<FormField
dataTestId="token-id"
titleText={t('tokenId')}
placeholder={t('nftTokenIdPlaceholder')}
value={tokenId}
onChange={(val) => {
validateAndSetTokenId(val);
setCollectibleAddFailed(false);
}}
tooltipText={t('importNFTTokenIdToolTip')}
/>
</Box>
</Box>
}
/>
);
}