From 93731a532ec73ab4409f62ddedd53b894c483a96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20Mi=C3=B1o?= Date: Mon, 4 Feb 2019 16:57:04 -0300 Subject: [PATCH] Block add custom collectible when user is not the owner (#359) * block add custom collectible when user not owner * test * handle contract errors * change locale --- app/components/AddCustomCollectible/index.js | 43 ++++++++++++++++--- .../AddCustomCollectible/index.test.js | 19 +++++++- locales/en.json | 2 + 3 files changed, 57 insertions(+), 7 deletions(-) diff --git a/app/components/AddCustomCollectible/index.js b/app/components/AddCustomCollectible/index.js index 053cb78d144..058542c4d25 100644 --- a/app/components/AddCustomCollectible/index.js +++ b/app/components/AddCustomCollectible/index.js @@ -1,11 +1,12 @@ import React, { Component } from 'react'; -import { Text, TextInput, View, StyleSheet } from 'react-native'; +import { Alert, Text, TextInput, View, StyleSheet } from 'react-native'; import { colors, fontStyles } from '../../styles/common'; import Engine from '../../core/Engine'; import PropTypes from 'prop-types'; import { strings } from '../../../locales/i18n'; import { isValidAddress } from 'ethereumjs-util'; import ActionView from '../ActionView'; +import { connect } from 'react-redux'; const styles = StyleSheet.create({ wrapper: { @@ -29,9 +30,9 @@ const styles = StyleSheet.create({ }); /** - * Copmonent that provides ability to add custom collectibles. + * Component that provides ability to add custom collectibles. */ -export default class AddCustomCollectible extends Component { +class AddCustomCollectible extends Component { state = { address: '', tokenId: '' @@ -41,11 +42,20 @@ export default class AddCustomCollectible extends Component { /** /* navigation object required to push new views */ - navigation: PropTypes.object + navigation: PropTypes.object, + /** + * A string that represents the selected address + */ + selectedAddress: PropTypes.string }; - addCollectible = () => { + addCollectible = async () => { if (!this.validateCustomCollectible()) return; + const isOwner = await this.validateCollectibleOwnership(); + if (!isOwner) { + this.handleNotCollectibleOwner(); + return; + } const { AssetsController } = Engine.context; const { address, tokenId } = this.state; AssetsController.addCollectible(address, tokenId); @@ -104,6 +114,23 @@ export default class AddCustomCollectible extends Component { current && current.focus(); }; + handleNotCollectibleOwner = () => { + Alert.alert(strings('collectible.ownership_error_title'), strings('collectible.ownership_error')); + }; + + validateCollectibleOwnership = async () => { + const { AssetsContractController } = Engine.context; + const { address, tokenId } = this.state; + const { selectedAddress } = this.props; + try { + const owner = await AssetsContractController.getOwnerOf(address, tokenId); + const isOwner = owner.toLowerCase() === selectedAddress.toLowerCase(); + return isOwner; + } catch (e) { + return false; + } + }; + render = () => ( ); } + +const mapStateToProps = state => ({ + selectedAddress: state.engine.backgroundState.PreferencesController.selectedAddress +}); + +export default connect(mapStateToProps)(AddCustomCollectible); diff --git a/app/components/AddCustomCollectible/index.test.js b/app/components/AddCustomCollectible/index.test.js index a9cca6c7dfb..6bf88ac87b3 100644 --- a/app/components/AddCustomCollectible/index.test.js +++ b/app/components/AddCustomCollectible/index.test.js @@ -1,10 +1,25 @@ import React from 'react'; import { shallow } from 'enzyme'; import AddCustomCollectible from './'; +import configureMockStore from 'redux-mock-store'; + +const mockStore = configureMockStore(); describe('AddCustomCollectible', () => { it('should render correctly', () => { - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const initialState = { + engine: { + backgroundState: { + PreferencesController: { + selectedAddress: '0x1' + } + } + } + }; + + const wrapper = shallow(, { + context: { store: mockStore(initialState) } + }); + expect(wrapper.dive()).toMatchSnapshot(); }); }); diff --git a/locales/en.json b/locales/en.json index 31efe320edb..d0f25db71eb 100644 --- a/locales/en.json +++ b/locales/en.json @@ -130,6 +130,8 @@ "address_must_be_valid": "Collectible address must be a valid address.", "address_cant_be_empty": "Collectible address can't be empty.", "token_id_cant_be_empty": "Collectible identifier can't be empty.", + "ownership_error_title": "Ooops! Something happened.", + "ownership_error": "You are not the owner of this collectible, so you can't add it.", "powered_by_opensea": "Powered by" }, "transfer": {