mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Feat/add collectible manually (#12834)
* hook up add collectible manually flow * address feedback
This commit is contained in:
parent
609f541b76
commit
5aa191fd2e
@ -1680,6 +1680,12 @@
|
|||||||
"message": "Account $1",
|
"message": "Account $1",
|
||||||
"description": "Default name of next account to be created on create account screen"
|
"description": "Default name of next account to be created on create account screen"
|
||||||
},
|
},
|
||||||
|
"newCollectibleAddFailed": {
|
||||||
|
"message": "Collectible was not added because: $1"
|
||||||
|
},
|
||||||
|
"newCollectibleAddedMessage": {
|
||||||
|
"message": "Collectible was successfully added!"
|
||||||
|
},
|
||||||
"newContact": {
|
"newContact": {
|
||||||
"message": "New Contact"
|
"message": "New Contact"
|
||||||
},
|
},
|
||||||
|
@ -183,7 +183,9 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
state: initState.TokensController,
|
state: initState.TokensController,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.assetsContractController = new AssetsContractController();
|
this.assetsContractController = new AssetsContractController({
|
||||||
|
provider: this.provider,
|
||||||
|
});
|
||||||
|
|
||||||
this.collectiblesController = new CollectiblesController({
|
this.collectiblesController = new CollectiblesController({
|
||||||
onPreferencesStateChange: this.preferencesController.store.subscribe.bind(
|
onPreferencesStateChange: this.preferencesController.store.subscribe.bind(
|
||||||
@ -588,6 +590,7 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.networkController.lookupNetwork();
|
this.networkController.lookupNetwork();
|
||||||
this.messageManager = new MessageManager({
|
this.messageManager = new MessageManager({
|
||||||
metricsEvent: this.metaMetricsController.trackEvent.bind(
|
metricsEvent: this.metaMetricsController.trackEvent.bind(
|
||||||
@ -1046,6 +1049,11 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
collectiblesController,
|
collectiblesController,
|
||||||
),
|
),
|
||||||
|
|
||||||
|
addCollectibleVerifyOwnership: nodeify(
|
||||||
|
collectiblesController.addCollectibleVerifyOwnership,
|
||||||
|
collectiblesController,
|
||||||
|
),
|
||||||
|
|
||||||
removeAndIgnoreCollectible: nodeify(
|
removeAndIgnoreCollectible: nodeify(
|
||||||
collectiblesController.removeAndIgnoreCollectible,
|
collectiblesController.removeAndIgnoreCollectible,
|
||||||
collectiblesController,
|
collectiblesController,
|
||||||
|
@ -111,7 +111,7 @@
|
|||||||
"@keystonehq/metamask-airgapped-keyring": "0.2.1",
|
"@keystonehq/metamask-airgapped-keyring": "0.2.1",
|
||||||
"@material-ui/core": "^4.11.0",
|
"@material-ui/core": "^4.11.0",
|
||||||
"@metamask/contract-metadata": "^1.28.0",
|
"@metamask/contract-metadata": "^1.28.0",
|
||||||
"@metamask/controllers": "^20.0.0",
|
"@metamask/controllers": "^20.1.0",
|
||||||
"@metamask/eth-ledger-bridge-keyring": "^0.10.0",
|
"@metamask/eth-ledger-bridge-keyring": "^0.10.0",
|
||||||
"@metamask/eth-token-tracker": "^3.0.1",
|
"@metamask/eth-token-tracker": "^3.0.1",
|
||||||
"@metamask/etherscan-link": "^2.1.0",
|
"@metamask/etherscan-link": "^2.1.0",
|
||||||
|
@ -55,6 +55,7 @@ export default function reduceApp(state = {}, action) {
|
|||||||
ledgerWebHidConnectedStatus: WEBHID_CONNECTED_STATUSES.UNKNOWN,
|
ledgerWebHidConnectedStatus: WEBHID_CONNECTED_STATUSES.UNKNOWN,
|
||||||
ledgerTransportStatus: TRANSPORT_STATES.NONE,
|
ledgerTransportStatus: TRANSPORT_STATES.NONE,
|
||||||
newNetworkAdded: '',
|
newNetworkAdded: '',
|
||||||
|
newCollectibleAddedMessage: '',
|
||||||
...state,
|
...state,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -290,6 +291,12 @@ export default function reduceApp(state = {}, action) {
|
|||||||
newNetworkAdded: action.value,
|
newNetworkAdded: action.value,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
case actionConstants.SET_NEW_COLLECTIBLE_ADDED_MESSAGE:
|
||||||
|
return {
|
||||||
|
...appState,
|
||||||
|
newCollectibleAddedMessage: action.value,
|
||||||
|
};
|
||||||
|
|
||||||
case actionConstants.LOADING_METHOD_DATA_STARTED:
|
case actionConstants.LOADING_METHOD_DATA_STARTED:
|
||||||
return {
|
return {
|
||||||
...appState,
|
...appState,
|
||||||
|
@ -1,27 +1,43 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
import { useI18nContext } from '../../hooks/useI18nContext';
|
import { useI18nContext } from '../../hooks/useI18nContext';
|
||||||
import { DEFAULT_ROUTE } from '../../helpers/constants/routes';
|
import { DEFAULT_ROUTE } from '../../helpers/constants/routes';
|
||||||
|
|
||||||
import Box from '../../components/ui/box';
|
import Box from '../../components/ui/box';
|
||||||
import TextField from '../../components/ui/text-field';
|
import TextField from '../../components/ui/text-field';
|
||||||
import PageContainer from '../../components/ui/page-container';
|
import PageContainer from '../../components/ui/page-container';
|
||||||
|
import {
|
||||||
|
addCollectibleVerifyOwnership,
|
||||||
|
setNewCollectibleAddedMessage,
|
||||||
|
} from '../../store/actions';
|
||||||
|
|
||||||
export default function AddCollectible() {
|
export default function AddCollectible() {
|
||||||
const t = useI18nContext();
|
const t = useI18nContext();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const [address, setAddress] = useState('');
|
const [address, setAddress] = useState('');
|
||||||
const [tokenId, setTokenId] = useState('');
|
const [tokenId, setTokenId] = useState('');
|
||||||
|
|
||||||
|
const handleAddCollectible = async () => {
|
||||||
|
try {
|
||||||
|
await dispatch(addCollectibleVerifyOwnership(address, tokenId));
|
||||||
|
} catch (error) {
|
||||||
|
const { message } = error;
|
||||||
|
dispatch(setNewCollectibleAddedMessage(message));
|
||||||
|
history.push(DEFAULT_ROUTE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dispatch(setNewCollectibleAddedMessage('success'));
|
||||||
|
history.push(DEFAULT_ROUTE);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContainer
|
<PageContainer
|
||||||
title={t('addNFT')}
|
title={t('addNFT')}
|
||||||
onSubmit={() => {
|
onSubmit={() => {
|
||||||
console.log(
|
handleAddCollectible();
|
||||||
`Adding collectible with ID: ${tokenId} and address ${address}`,
|
|
||||||
);
|
|
||||||
history.push(DEFAULT_ROUTE);
|
|
||||||
}}
|
}}
|
||||||
submitText={t('add')}
|
submitText={t('add')}
|
||||||
onCancel={() => {
|
onCancel={() => {
|
||||||
|
@ -92,6 +92,8 @@ export default class Home extends PureComponent {
|
|||||||
newNetworkAdded: PropTypes.string,
|
newNetworkAdded: PropTypes.string,
|
||||||
setNewNetworkAdded: PropTypes.func.isRequired,
|
setNewNetworkAdded: PropTypes.func.isRequired,
|
||||||
isSigningQRHardwareTransaction: PropTypes.bool.isRequired,
|
isSigningQRHardwareTransaction: PropTypes.bool.isRequired,
|
||||||
|
newCollectibleAddedMessage: PropTypes.string,
|
||||||
|
setNewCollectibleAddedMessage: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
@ -225,9 +227,42 @@ export default class Home extends PureComponent {
|
|||||||
infuraBlocked,
|
infuraBlocked,
|
||||||
newNetworkAdded,
|
newNetworkAdded,
|
||||||
setNewNetworkAdded,
|
setNewNetworkAdded,
|
||||||
|
newCollectibleAddedMessage,
|
||||||
|
setNewCollectibleAddedMessage,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
return (
|
return (
|
||||||
<MultipleNotifications>
|
<MultipleNotifications>
|
||||||
|
{newCollectibleAddedMessage ? (
|
||||||
|
<ActionableMessage
|
||||||
|
type={newCollectibleAddedMessage === 'success' ? 'info' : 'warning'}
|
||||||
|
className="home__new-network-notification"
|
||||||
|
message={
|
||||||
|
<div className="home__new-network-notification-message">
|
||||||
|
{newCollectibleAddedMessage === 'success' ? (
|
||||||
|
<img
|
||||||
|
src="./images/check_circle.svg"
|
||||||
|
className="home__new-network-notification-message--image"
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
<Typography
|
||||||
|
variant={TYPOGRAPHY.H7}
|
||||||
|
fontWeight={FONT_WEIGHT.NORMAL}
|
||||||
|
>
|
||||||
|
{newCollectibleAddedMessage === 'success'
|
||||||
|
? t('newCollectibleAddedMessage')
|
||||||
|
: t('newCollectibleAddFailed', [
|
||||||
|
newCollectibleAddedMessage,
|
||||||
|
])}
|
||||||
|
</Typography>
|
||||||
|
<button
|
||||||
|
className="fas fa-times home__close"
|
||||||
|
title={t('close')}
|
||||||
|
onClick={() => setNewCollectibleAddedMessage('')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
{newNetworkAdded ? (
|
{newNetworkAdded ? (
|
||||||
<ActionableMessage
|
<ActionableMessage
|
||||||
type="info"
|
type="info"
|
||||||
@ -242,7 +277,7 @@ export default class Home extends PureComponent {
|
|||||||
variant={TYPOGRAPHY.H7}
|
variant={TYPOGRAPHY.H7}
|
||||||
fontWeight={FONT_WEIGHT.NORMAL}
|
fontWeight={FONT_WEIGHT.NORMAL}
|
||||||
>
|
>
|
||||||
{this.context.t('newNetworkAdded', [newNetworkAdded])}
|
{t('newNetworkAdded', [newNetworkAdded])}
|
||||||
</Typography>
|
</Typography>
|
||||||
<button
|
<button
|
||||||
className="fas fa-times home__close"
|
className="fas fa-times home__close"
|
||||||
|
@ -18,6 +18,7 @@ import {
|
|||||||
getNewNetworkAdded,
|
getNewNetworkAdded,
|
||||||
hasUnsignedQRHardwareTransaction,
|
hasUnsignedQRHardwareTransaction,
|
||||||
hasUnsignedQRHardwareMessage,
|
hasUnsignedQRHardwareMessage,
|
||||||
|
getNewCollectibleAddedMessage,
|
||||||
} from '../../selectors';
|
} from '../../selectors';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -32,6 +33,7 @@ import {
|
|||||||
setRecoveryPhraseReminderHasBeenShown,
|
setRecoveryPhraseReminderHasBeenShown,
|
||||||
setRecoveryPhraseReminderLastShown,
|
setRecoveryPhraseReminderLastShown,
|
||||||
setNewNetworkAdded,
|
setNewNetworkAdded,
|
||||||
|
setNewCollectibleAddedMessage,
|
||||||
} from '../../store/actions';
|
} from '../../store/actions';
|
||||||
import { setThreeBoxLastUpdated, hideWhatsNewPopup } from '../../ducks/app/app';
|
import { setThreeBoxLastUpdated, hideWhatsNewPopup } from '../../ducks/app/app';
|
||||||
import { getWeb3ShimUsageAlertEnabledness } from '../../ducks/metamask/metamask';
|
import { getWeb3ShimUsageAlertEnabledness } from '../../ducks/metamask/metamask';
|
||||||
@ -122,6 +124,7 @@ const mapStateToProps = (state) => {
|
|||||||
seedPhraseBackedUp,
|
seedPhraseBackedUp,
|
||||||
newNetworkAdded: getNewNetworkAdded(state),
|
newNetworkAdded: getNewNetworkAdded(state),
|
||||||
isSigningQRHardwareTransaction,
|
isSigningQRHardwareTransaction,
|
||||||
|
newCollectibleAddedMessage: getNewCollectibleAddedMessage(state),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -154,6 +157,9 @@ const mapDispatchToProps = (dispatch) => ({
|
|||||||
setNewNetworkAdded: (newNetwork) => {
|
setNewNetworkAdded: (newNetwork) => {
|
||||||
dispatch(setNewNetworkAdded(newNetwork));
|
dispatch(setNewNetworkAdded(newNetwork));
|
||||||
},
|
},
|
||||||
|
setNewCollectibleAddedMessage: (message) => {
|
||||||
|
dispatch(setNewCollectibleAddedMessage(message));
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
|
@ -735,6 +735,10 @@ export function doesAddressRequireLedgerHidConnection(state, address) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getNewCollectibleAddedMessage(state) {
|
||||||
|
return state.appState.newCollectibleAddedMessage;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To retrieve the name of the new Network added using add network form
|
* To retrieve the name of the new Network added using add network form
|
||||||
* @param {*} state
|
* @param {*} state
|
||||||
|
@ -90,6 +90,8 @@ export const SET_FIRST_TIME_FLOW_TYPE = 'SET_FIRST_TIME_FLOW_TYPE';
|
|||||||
|
|
||||||
export const SET_SELECTED_SETTINGS_RPC_URL = 'SET_SELECTED_SETTINGS_RPC_URL';
|
export const SET_SELECTED_SETTINGS_RPC_URL = 'SET_SELECTED_SETTINGS_RPC_URL';
|
||||||
export const SET_NEW_NETWORK_ADDED = 'SET_NEW_NETWORK_ADDED';
|
export const SET_NEW_NETWORK_ADDED = 'SET_NEW_NETWORK_ADDED';
|
||||||
|
export const SET_NEW_COLLECTIBLE_ADDED_MESSAGE =
|
||||||
|
'SET_NEW_COLLECTIBLE_ADDED_MESSAGE';
|
||||||
|
|
||||||
export const LOADING_METHOD_DATA_STARTED = 'LOADING_METHOD_DATA_STARTED';
|
export const LOADING_METHOD_DATA_STARTED = 'LOADING_METHOD_DATA_STARTED';
|
||||||
export const LOADING_METHOD_DATA_FINISHED = 'LOADING_METHOD_DATA_FINISHED';
|
export const LOADING_METHOD_DATA_FINISHED = 'LOADING_METHOD_DATA_FINISHED';
|
||||||
|
@ -1317,6 +1317,43 @@ export function addCollectible(address, tokenID, dontShowLoadingIndicator) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function addCollectibleVerifyOwnership(
|
||||||
|
address,
|
||||||
|
tokenID,
|
||||||
|
dontShowLoadingIndicator,
|
||||||
|
) {
|
||||||
|
return async (dispatch) => {
|
||||||
|
if (!address) {
|
||||||
|
throw new Error('MetaMask - Cannot add collectible without address');
|
||||||
|
}
|
||||||
|
if (!tokenID) {
|
||||||
|
throw new Error('MetaMask - Cannot add collectible without tokenID');
|
||||||
|
}
|
||||||
|
if (!dontShowLoadingIndicator) {
|
||||||
|
dispatch(showLoadingIndication());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await promisifiedBackground.addCollectibleVerifyOwnership(
|
||||||
|
address,
|
||||||
|
tokenID,
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
if (
|
||||||
|
error.message.includes('This collectible is not owned by the user') ||
|
||||||
|
error.message.includes('Unable to verify ownership.')
|
||||||
|
) {
|
||||||
|
throw error;
|
||||||
|
} else {
|
||||||
|
log.error(error);
|
||||||
|
dispatch(displayWarning(error.message));
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
await forceUpdateMetamaskState(dispatch);
|
||||||
|
dispatch(hideLoadingIndication());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function removeAndIgnoreCollectible(
|
export function removeAndIgnoreCollectible(
|
||||||
address,
|
address,
|
||||||
tokenID,
|
tokenID,
|
||||||
@ -2552,6 +2589,13 @@ export function setNewNetworkAdded(newNetworkAdded) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setNewCollectibleAddedMessage(newCollectibleAddedMessage) {
|
||||||
|
return {
|
||||||
|
type: actionConstants.SET_NEW_COLLECTIBLE_ADDED_MESSAGE,
|
||||||
|
value: newCollectibleAddedMessage,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function setLastActiveTime() {
|
export function setLastActiveTime() {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
background.setLastActiveTime((err) => {
|
background.setLastActiveTime((err) => {
|
||||||
|
@ -2606,10 +2606,10 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@metamask/contract-metadata/-/contract-metadata-1.30.0.tgz#fa8e1b0c3e7aaa963986088f691fb553ffbe3904"
|
resolved "https://registry.yarnpkg.com/@metamask/contract-metadata/-/contract-metadata-1.30.0.tgz#fa8e1b0c3e7aaa963986088f691fb553ffbe3904"
|
||||||
integrity sha512-b2usYW/ptQYnE6zhUmr4T+nvOAQJK5ABcpKudyQANpy4K099elpv4aN0WcrcOcwV99NHOdMzFP3ZuG0HoAyOBQ==
|
integrity sha512-b2usYW/ptQYnE6zhUmr4T+nvOAQJK5ABcpKudyQANpy4K099elpv4aN0WcrcOcwV99NHOdMzFP3ZuG0HoAyOBQ==
|
||||||
|
|
||||||
"@metamask/controllers@^20.0.0":
|
"@metamask/controllers@^20.1.0":
|
||||||
version "20.0.0"
|
version "20.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-20.0.0.tgz#5c3fd293e1c8d3de964bbbfadbd73d637d83a1a8"
|
resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-20.1.0.tgz#1d8386dc22d14f9fd9feb8b3cc8314d663587550"
|
||||||
integrity sha512-H7ql719730+KCFRvAxWVKe3PvEabKgA9b+0+k4/nRA2Xvb7Pe3BlQ4lgt44wOFKDqdWyvwvH7mgNTAhDzBu4OA==
|
integrity sha512-Z/7uLGXZWbCBbtCybR3jo1bx3mcvZRUSm1i43od4dnJoQo2+Veq4ePrFVgPKS3WtLIM/hzZuI7UTAQ9HNX9aew==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@ethereumjs/common" "^2.3.1"
|
"@ethereumjs/common" "^2.3.1"
|
||||||
"@ethereumjs/tx" "^3.2.1"
|
"@ethereumjs/tx" "^3.2.1"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user