Merge pull request #3768 from ethcore/jr-use-badge-reg
get certifications from BadgeReg, show them in accounts overview
This commit is contained in:
commit
d76239ed48
@ -18,7 +18,8 @@ import { bytesToHex, hex2Ascii } from '~/api/util/format';
|
|||||||
|
|
||||||
import ABI from './abi/certifier.json';
|
import ABI from './abi/certifier.json';
|
||||||
|
|
||||||
const ZERO = '0x0000000000000000000000000000000000000000000000000000000000000000';
|
const ZERO20 = '0x0000000000000000000000000000000000000000';
|
||||||
|
const ZERO32 = '0x0000000000000000000000000000000000000000000000000000000000000000';
|
||||||
|
|
||||||
export default class BadgeReg {
|
export default class BadgeReg {
|
||||||
constructor (api, registry) {
|
constructor (api, registry) {
|
||||||
@ -26,32 +27,57 @@ export default class BadgeReg {
|
|||||||
this._registry = registry;
|
this._registry = registry;
|
||||||
|
|
||||||
registry.getContract('badgereg');
|
registry.getContract('badgereg');
|
||||||
this.certifiers = {}; // by name
|
this.certifiers = []; // by id
|
||||||
this.contracts = {}; // by name
|
this.contracts = {}; // by name
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchCertifier (name) {
|
certifierCount () {
|
||||||
if (this.certifiers[name]) {
|
return this._registry.getContract('badgereg')
|
||||||
return Promise.resolve(this.certifiers[name]);
|
.then((badgeReg) => {
|
||||||
|
return badgeReg.instance.badgeCount.call({}, [])
|
||||||
|
.then((count) => count.valueOf());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchCertifier (id) {
|
||||||
|
if (this.certifiers[id]) {
|
||||||
|
return Promise.resolve(this.certifiers[id]);
|
||||||
}
|
}
|
||||||
return this._registry.getContract('badgereg')
|
return this._registry.getContract('badgereg')
|
||||||
.then((badgeReg) => {
|
.then((badgeReg) => {
|
||||||
return badgeReg.instance.fromName.call({}, [name])
|
return badgeReg.instance.badge.call({}, [ id ]);
|
||||||
.then(([ id, address ]) => {
|
})
|
||||||
return Promise.all([
|
.then(([ address, name ]) => {
|
||||||
badgeReg.instance.meta.call({}, [id, 'TITLE']),
|
if (address === ZERO20) {
|
||||||
badgeReg.instance.meta.call({}, [id, 'IMG'])
|
throw new Error(`Certifier ${id} does not exist.`);
|
||||||
])
|
}
|
||||||
.then(([ title, img ]) => {
|
|
||||||
title = bytesToHex(title);
|
|
||||||
title = title === ZERO ? null : hex2Ascii(title);
|
|
||||||
if (bytesToHex(img) === ZERO) img = null;
|
|
||||||
|
|
||||||
const data = { address, name, title, icon: img };
|
name = bytesToHex(name);
|
||||||
this.certifiers[name] = data;
|
name = name === ZERO32
|
||||||
|
? null
|
||||||
|
: hex2Ascii(name);
|
||||||
|
return this.fetchMeta(id)
|
||||||
|
.then(({ title, icon }) => {
|
||||||
|
const data = { address, id, name, title, icon };
|
||||||
|
this.certifiers[id] = data;
|
||||||
return data;
|
return data;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchMeta (id) {
|
||||||
|
return this._registry.getContract('badgereg')
|
||||||
|
.then((badgeReg) => {
|
||||||
|
return Promise.all([
|
||||||
|
badgeReg.instance.meta.call({}, [id, 'TITLE']),
|
||||||
|
badgeReg.instance.meta.call({}, [id, 'IMG'])
|
||||||
|
]);
|
||||||
|
})
|
||||||
|
.then(([ title, icon ]) => {
|
||||||
|
title = bytesToHex(title);
|
||||||
|
title = title === ZERO32 ? null : hex2Ascii(title);
|
||||||
|
if (bytesToHex(icon) === ZERO32) icon = null;
|
||||||
|
return { title, icon };
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,10 +14,18 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
export const fetchCertifiers = () => ({
|
||||||
|
type: 'fetchCertifiers'
|
||||||
|
});
|
||||||
|
|
||||||
export const fetchCertifications = (address) => ({
|
export const fetchCertifications = (address) => ({
|
||||||
type: 'fetchCertifications', address
|
type: 'fetchCertifications', address
|
||||||
});
|
});
|
||||||
|
|
||||||
export const addCertification = (address, name, title, icon) => ({
|
export const addCertification = (address, id, name, title, icon) => ({
|
||||||
type: 'addCertification', address, name, title, icon
|
type: 'addCertification', address, id, name, title, icon
|
||||||
|
});
|
||||||
|
|
||||||
|
export const removeCertification = (address, id) => ({
|
||||||
|
type: 'removeCertification', address, id
|
||||||
});
|
});
|
||||||
|
@ -14,38 +14,90 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import Contracts from '~/contracts';
|
import { uniq } from 'lodash';
|
||||||
import { addCertification } from './actions';
|
|
||||||
|
|
||||||
const knownCertifiers = [ 'smsverification' ];
|
import ABI from '~/contracts/abi/certifier.json';
|
||||||
|
import Contract from '~/api/contract';
|
||||||
|
import Contracts from '~/contracts';
|
||||||
|
import { addCertification, removeCertification } from './actions';
|
||||||
|
|
||||||
export default class CertificationsMiddleware {
|
export default class CertificationsMiddleware {
|
||||||
toMiddleware () {
|
toMiddleware () {
|
||||||
return (store) => (next) => (action) => {
|
const api = Contracts.get()._api;
|
||||||
if (action.type !== 'fetchCertifications') {
|
|
||||||
return next(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
const { address } = action;
|
|
||||||
const badgeReg = Contracts.get().badgeReg;
|
const badgeReg = Contracts.get().badgeReg;
|
||||||
|
const contract = new Contract(api, ABI);
|
||||||
|
const Confirmed = contract.events.find((e) => e.name === 'Confirmed');
|
||||||
|
const Revoked = contract.events.find((e) => e.name === 'Revoked');
|
||||||
|
|
||||||
knownCertifiers.forEach((name) => {
|
let certifiers = [];
|
||||||
badgeReg.fetchCertifier(name)
|
let accounts = []; // these are addresses
|
||||||
.then((cert) => {
|
|
||||||
return badgeReg.checkIfCertified(cert.address, address)
|
const fetchConfirmedEvents = (dispatch) => {
|
||||||
.then((isCertified) => {
|
if (certifiers.length === 0 || accounts.length === 0) return;
|
||||||
if (isCertified) {
|
api.eth.getLogs({
|
||||||
const { name, title, icon } = cert;
|
fromBlock: 0,
|
||||||
store.dispatch(addCertification(address, name, title, icon));
|
toBlock: 'latest',
|
||||||
|
address: certifiers.map((c) => c.address),
|
||||||
|
topics: [ [ Confirmed.signature, Revoked.signature ], accounts ]
|
||||||
|
})
|
||||||
|
.then((logs) => contract.parseEventLogs(logs))
|
||||||
|
.then((logs) => {
|
||||||
|
logs.forEach((log) => {
|
||||||
|
const certifier = certifiers.find((c) => c.address === log.address);
|
||||||
|
if (!certifier) {
|
||||||
|
throw new Error(`Could not find certifier at ${log.address}.`);
|
||||||
|
}
|
||||||
|
const { id, name, title, icon } = certifier;
|
||||||
|
|
||||||
|
if (log.event === 'Revoked') {
|
||||||
|
dispatch(removeCertification(log.params.who.value, id));
|
||||||
|
} else {
|
||||||
|
dispatch(addCertification(log.params.who.value, id, name, title, icon));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
if (err) {
|
console.error('Failed to fetch Confirmed events:', err);
|
||||||
console.error(`Failed to check if ${address} certified by ${name}:`, err);
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (store) => (next) => (action) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case 'fetchCertifiers':
|
||||||
|
badgeReg.certifierCount().then((count) => {
|
||||||
|
new Array(+count).fill(null).forEach((_, id) => {
|
||||||
|
badgeReg.fetchCertifier(id)
|
||||||
|
.then((cert) => {
|
||||||
|
if (!certifiers.some((c) => c.id === cert.id)) {
|
||||||
|
certifiers = certifiers.concat(cert);
|
||||||
|
fetchConfirmedEvents(store.dispatch);
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.warn(`Could not fetch certifier ${id}:`, err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'fetchCertifications':
|
||||||
|
const { address } = action;
|
||||||
|
|
||||||
|
if (!accounts.includes(address)) {
|
||||||
|
accounts = accounts.concat(address);
|
||||||
|
fetchConfirmedEvents(store.dispatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'setVisibleAccounts':
|
||||||
|
const { addresses } = action;
|
||||||
|
accounts = uniq(accounts.concat(addresses));
|
||||||
|
fetchConfirmedEvents(store.dispatch);
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
next(action);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,17 +17,27 @@
|
|||||||
const initialState = {};
|
const initialState = {};
|
||||||
|
|
||||||
export default (state = initialState, action) => {
|
export default (state = initialState, action) => {
|
||||||
if (action.type !== 'addCertification') {
|
if (action.type === 'addCertification') {
|
||||||
return state;
|
const { address, id, name, icon, title } = action;
|
||||||
}
|
|
||||||
|
|
||||||
const { address, name, icon, title } = action;
|
|
||||||
const certifications = state[address] || [];
|
const certifications = state[address] || [];
|
||||||
|
|
||||||
if (certifications.some((c) => c.name === name)) {
|
if (certifications.some((c) => c.id === id)) {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
const newCertifications = certifications.concat({ name, icon, title });
|
|
||||||
|
|
||||||
|
const newCertifications = certifications.concat({
|
||||||
|
id, name, icon, title
|
||||||
|
});
|
||||||
return { ...state, [address]: newCertifications };
|
return { ...state, [address]: newCertifications };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action.type === 'removeCertification') {
|
||||||
|
const { address, id } = action;
|
||||||
|
const certifications = state[address] || [];
|
||||||
|
|
||||||
|
const newCertifications = certifications.filter((c) => c.id !== id);
|
||||||
|
return { ...state, [address]: newCertifications };
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
};
|
};
|
||||||
|
@ -16,10 +16,8 @@
|
|||||||
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
|
|
||||||
import { hashToImageUrl } from '~/redux/providers/imagesReducer';
|
import { hashToImageUrl } from '~/redux/providers/imagesReducer';
|
||||||
import { fetchCertifications } from '~/redux/providers/certifications/actions';
|
|
||||||
|
|
||||||
import defaultIcon from '../../../assets/images/certifications/unknown.svg';
|
import defaultIcon from '../../../assets/images/certifications/unknown.svg';
|
||||||
|
|
||||||
@ -29,14 +27,7 @@ class Certifications extends Component {
|
|||||||
static propTypes = {
|
static propTypes = {
|
||||||
account: PropTypes.string.isRequired,
|
account: PropTypes.string.isRequired,
|
||||||
certifications: PropTypes.array.isRequired,
|
certifications: PropTypes.array.isRequired,
|
||||||
dappsUrl: PropTypes.string.isRequired,
|
dappsUrl: PropTypes.string.isRequired
|
||||||
|
|
||||||
fetchCertifications: PropTypes.func.isRequired
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillMount () {
|
|
||||||
const { account, fetchCertifications } = this.props;
|
|
||||||
fetchCertifications(account);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
@ -73,15 +64,13 @@ function mapStateToProps (_, initProps) {
|
|||||||
|
|
||||||
return (state) => {
|
return (state) => {
|
||||||
const certifications = state.certifications[account] || [];
|
const certifications = state.certifications[account] || [];
|
||||||
return { certifications };
|
const dappsUrl = state.api.dappsUrl;
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
return { certifications, dappsUrl };
|
||||||
return bindActionCreators({ fetchCertifications }, dispatch);
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
null
|
||||||
)(Certifications);
|
)(Certifications);
|
||||||
|
@ -23,10 +23,6 @@ import Certifications from '~/ui/Certifications';
|
|||||||
import styles from './header.css';
|
import styles from './header.css';
|
||||||
|
|
||||||
export default class Header extends Component {
|
export default class Header extends Component {
|
||||||
static contextTypes = {
|
|
||||||
api: PropTypes.object
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
account: PropTypes.object,
|
account: PropTypes.object,
|
||||||
balance: PropTypes.object,
|
balance: PropTypes.object,
|
||||||
@ -44,7 +40,6 @@ export default class Header extends Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { api } = this.context;
|
|
||||||
const { account, balance, className, children, hideName } = this.props;
|
const { account, balance, className, children, hideName } = this.props;
|
||||||
const { address, meta, uuid } = account;
|
const { address, meta, uuid } = account;
|
||||||
|
|
||||||
@ -85,7 +80,6 @@ export default class Header extends Component {
|
|||||||
balance={ balance } />
|
balance={ balance } />
|
||||||
<Certifications
|
<Certifications
|
||||||
account={ account.address }
|
account={ account.address }
|
||||||
dappsUrl={ api.dappsUrl }
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{ children }
|
{ children }
|
||||||
|
@ -31,6 +31,7 @@ import shapeshiftBtn from '~/../assets/images/shapeshift-btn.png';
|
|||||||
import Header from './Header';
|
import Header from './Header';
|
||||||
import Transactions from './Transactions';
|
import Transactions from './Transactions';
|
||||||
import { setVisibleAccounts } from '~/redux/providers/personalActions';
|
import { setVisibleAccounts } from '~/redux/providers/personalActions';
|
||||||
|
import { fetchCertifiers, fetchCertifications } from '~/redux/providers/certifications/actions';
|
||||||
|
|
||||||
import SMSVerificationStore from '~/modals/Verification/sms-store';
|
import SMSVerificationStore from '~/modals/Verification/sms-store';
|
||||||
import EmailVerificationStore from '~/modals/Verification/email-store';
|
import EmailVerificationStore from '~/modals/Verification/email-store';
|
||||||
@ -44,6 +45,8 @@ class Account extends Component {
|
|||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
setVisibleAccounts: PropTypes.func.isRequired,
|
setVisibleAccounts: PropTypes.func.isRequired,
|
||||||
|
fetchCertifiers: PropTypes.func.isRequired,
|
||||||
|
fetchCertifications: PropTypes.func.isRequired,
|
||||||
images: PropTypes.object.isRequired,
|
images: PropTypes.object.isRequired,
|
||||||
|
|
||||||
params: PropTypes.object,
|
params: PropTypes.object,
|
||||||
@ -63,6 +66,7 @@ class Account extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
|
this.props.fetchCertifiers();
|
||||||
this.setVisibleAccounts();
|
this.setVisibleAccounts();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,9 +84,10 @@ class Account extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setVisibleAccounts (props = this.props) {
|
setVisibleAccounts (props = this.props) {
|
||||||
const { params, setVisibleAccounts } = props;
|
const { params, setVisibleAccounts, fetchCertifications } = props;
|
||||||
const addresses = [ params.address ];
|
const addresses = [ params.address ];
|
||||||
setVisibleAccounts(addresses);
|
setVisibleAccounts(addresses);
|
||||||
|
fetchCertifications(params.address);
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
@ -353,7 +358,9 @@ function mapStateToProps (state) {
|
|||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
function mapDispatchToProps (dispatch) {
|
||||||
return bindActionCreators({
|
return bindActionCreators({
|
||||||
setVisibleAccounts
|
setVisibleAccounts,
|
||||||
|
fetchCertifiers,
|
||||||
|
fetchCertifications
|
||||||
}, dispatch);
|
}, dispatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,22 +15,29 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { bindActionCreators } from 'redux';
|
||||||
|
|
||||||
import { Container } from '~/ui';
|
import { Container } from '~/ui';
|
||||||
|
import { fetchCertifiers, fetchCertifications } from '~/redux/providers/certifications/actions';
|
||||||
|
|
||||||
import Summary from '../Summary';
|
import Summary from '../Summary';
|
||||||
import styles from './list.css';
|
import styles from './list.css';
|
||||||
|
|
||||||
export default class List extends Component {
|
class List extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
accounts: PropTypes.object,
|
accounts: PropTypes.object,
|
||||||
walletsOwners: PropTypes.object,
|
|
||||||
balances: PropTypes.object,
|
balances: PropTypes.object,
|
||||||
link: PropTypes.string,
|
certifications: PropTypes.object.isRequired,
|
||||||
search: PropTypes.array,
|
|
||||||
empty: PropTypes.bool,
|
empty: PropTypes.bool,
|
||||||
|
link: PropTypes.string,
|
||||||
order: PropTypes.string,
|
order: PropTypes.string,
|
||||||
orderFallback: PropTypes.string,
|
orderFallback: PropTypes.string,
|
||||||
|
search: PropTypes.array,
|
||||||
|
walletsOwners: PropTypes.object,
|
||||||
|
|
||||||
|
fetchCertifiers: PropTypes.func.isRequired,
|
||||||
|
fetchCertifications: PropTypes.func.isRequired,
|
||||||
handleAddSearchToken: PropTypes.func
|
handleAddSearchToken: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -42,8 +49,16 @@ export default class List extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillMount () {
|
||||||
|
const { accounts, fetchCertifiers, fetchCertifications } = this.props;
|
||||||
|
fetchCertifiers();
|
||||||
|
for (let address in accounts) {
|
||||||
|
fetchCertifications(address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
renderAccounts () {
|
renderAccounts () {
|
||||||
const { accounts, balances, link, empty, handleAddSearchToken, walletsOwners } = this.props;
|
const { accounts, balances, empty, link, walletsOwners, handleAddSearchToken } = this.props;
|
||||||
|
|
||||||
if (empty) {
|
if (empty) {
|
||||||
return (
|
return (
|
||||||
@ -72,7 +87,9 @@ export default class List extends Component {
|
|||||||
account={ account }
|
account={ account }
|
||||||
balance={ balance }
|
balance={ balance }
|
||||||
owners={ owners }
|
owners={ owners }
|
||||||
handleAddSearchToken={ handleAddSearchToken } />
|
handleAddSearchToken={ handleAddSearchToken }
|
||||||
|
showCertifications
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -207,3 +224,20 @@ export default class List extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mapStateToProps (state) {
|
||||||
|
const { certifications } = state;
|
||||||
|
return { certifications };
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapDispatchToProps (dispatch) {
|
||||||
|
return bindActionCreators({
|
||||||
|
fetchCertifiers,
|
||||||
|
fetchCertifications
|
||||||
|
}, dispatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(List);
|
||||||
|
@ -21,6 +21,7 @@ import { isEqual } from 'lodash';
|
|||||||
import ReactTooltip from 'react-tooltip';
|
import ReactTooltip from 'react-tooltip';
|
||||||
|
|
||||||
import { Balance, Container, ContainerTitle, IdentityIcon, IdentityName, Tags, Input } from '~/ui';
|
import { Balance, Container, ContainerTitle, IdentityIcon, IdentityName, Tags, Input } from '~/ui';
|
||||||
|
import Certifications from '~/ui/Certifications';
|
||||||
import { nullableProptype } from '~/util/proptypes';
|
import { nullableProptype } from '~/util/proptypes';
|
||||||
|
|
||||||
import styles from '../accounts.css';
|
import styles from '../accounts.css';
|
||||||
@ -36,12 +37,14 @@ export default class Summary extends Component {
|
|||||||
link: PropTypes.string,
|
link: PropTypes.string,
|
||||||
name: PropTypes.string,
|
name: PropTypes.string,
|
||||||
noLink: PropTypes.bool,
|
noLink: PropTypes.bool,
|
||||||
|
showCertifications: PropTypes.bool,
|
||||||
handleAddSearchToken: PropTypes.func,
|
handleAddSearchToken: PropTypes.func,
|
||||||
owners: nullableProptype(PropTypes.array)
|
owners: nullableProptype(PropTypes.array)
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
noLink: false
|
noLink: false,
|
||||||
|
showCertifications: false
|
||||||
};
|
};
|
||||||
|
|
||||||
shouldComponentUpdate (nextProps) {
|
shouldComponentUpdate (nextProps) {
|
||||||
@ -115,6 +118,7 @@ export default class Summary extends Component {
|
|||||||
|
|
||||||
{ this.renderOwners() }
|
{ this.renderOwners() }
|
||||||
{ this.renderBalance() }
|
{ this.renderBalance() }
|
||||||
|
{ this.renderCertifications() }
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -181,4 +185,15 @@ export default class Summary extends Component {
|
|||||||
<Balance balance={ balance } />
|
<Balance balance={ balance } />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderCertifications () {
|
||||||
|
const { showCertifications, account } = this.props;
|
||||||
|
if (!showCertifications) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Certifications account={ account.address } />
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user