Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Align contract event log l&f with transactions #2812

Merged
merged 3 commits into from
Oct 25, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion js/src/api/contract/contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,9 @@ export default class Contract {
log.event = event.name;

decoded.params.forEach((param) => {
log.params[param.name] = param.token.value;
const { type, value } = param.token;

log.params[param.name] = { type, value };
});

return log;
Expand Down
4 changes: 4 additions & 0 deletions js/src/dapps/basiccoin/Deploy/Events/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ export default class Events extends Component {

logToEvent = (log) => {
log.key = api.util.sha3(JSON.stringify(log));
log.params = Object.keys(log.params).reduce((params, name) => {
params[name] = log.params[name].value;
return params;
}, {});

return log;
}
Expand Down
5 changes: 4 additions & 1 deletion js/src/dapps/basiccoin/Transfer/Events/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ export default class Events extends Component {

logToEvent = (log) => {
log.key = api.util.sha3(JSON.stringify(log));
log.params = Object.keys(log.params).reduce((params, name) => {
params[name] = log.params[name].value;
return params;
}, {});

return log;
}
Expand All @@ -139,7 +143,6 @@ export default class Events extends Component {
.concat(pendingEvents)
.filter((log) => !minedNew.find((event) => event.transactionHash === log.transactionHash));
const events = [].concat(pendingNew).concat(minedNew);
console.log('*** events', events.map((event) => event.address));
this.setState({ loading: false, events, minedEvents: minedNew, pendingEvents: pendingNew });
}
}
5 changes: 4 additions & 1 deletion js/src/dapps/gavcoin/Events/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,10 @@ export default class Events extends Component {
logIndex,
transactionHash,
transactionIndex,
params,
params: Object.keys(params).reduce((data, name) => {
data[name] = params[name].value;
return data;
}, {}),
key
};
};
Expand Down
8 changes: 4 additions & 4 deletions js/src/dapps/registry/Events/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ const renderEvent = (classNames, verb) => (e, accounts, contacts) => {

return (
<tr key={ e.key } className={ classes }>
<td>{ renderAddress(e.parameters.owner, accounts, contacts) }</td>
<td>{ renderAddress(e.parameters.owner.value, accounts, contacts) }</td>
<td><abbr title={ e.transaction }>{ verb }</abbr></td>
<td><code>{ renderHash(bytesToHex(e.parameters.name)) }</code></td>
<td><code>{ renderHash(bytesToHex(e.parameters.name.value)) }</code></td>
<td>{ renderStatus(e.timestamp, e.state === 'pending') }</td>
</tr>
);
Expand All @@ -64,10 +64,10 @@ const renderDataChanged = (e, accounts, contacts) => {

return (
<tr key={ e.key } className={ classNames }>
<td>{ renderAddress(e.parameters.owner, accounts, contacts) }</td>
<td>{ renderAddress(e.parameters.owner.value, accounts, contacts) }</td>
<td><abbr title={ e.transaction }>updated</abbr></td>
<td>
key <code>{ new Buffer(e.parameters.plainKey).toString('utf8') }</code> of <code>{ renderHash(bytesToHex(e.parameters.name)) }</code>
key <code>{ new Buffer(e.parameters.plainKey.value).toString('utf8') }</code> of <code>{ renderHash(bytesToHex(e.parameters.name.value)) }</code>
</td>
<td>{ renderStatus(e.timestamp, e.state === 'pending') }</td>
</tr>
Expand Down
5 changes: 4 additions & 1 deletion js/src/dapps/signaturereg/services.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ const logToEvent = (log) => {
logIndex,
transactionHash,
transactionIndex,
params,
params: Object.keys(params).reduce((data, name) => {
data[name] = params[name].value;
return data;
}, {}),
key
};
};
Expand Down
16 changes: 8 additions & 8 deletions js/src/dapps/tokenreg/Status/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,41 +148,41 @@ export const subscribeEvents = () => (dispatch, getState) => {
return dispatch(setTokenData(params.id.toNumber(), {
tla: '...',
base: -1,
address: params.addr,
name: params.name,
address: params.addr.value,
name: params.name.value,
isPending: true
}));
}

if (event === 'Registered' && type === 'mined') {
return dispatch(loadToken(params.id.toNumber()));
return dispatch(loadToken(params.id.value.toNumber()));
}

if (event === 'Unregistered' && type === 'pending') {
return dispatch(setTokenPending(params.id.toNumber(), true));
return dispatch(setTokenPending(params.id.value.toNumber(), true));
}

if (event === 'Unregistered' && type === 'mined') {
return dispatch(deleteToken(params.id.toNumber()));
return dispatch(deleteToken(params.id.value.toNumber()));
}

if (event === 'MetaChanged' && type === 'pending') {
return dispatch(setTokenData(
params.id.toNumber(),
params.id.value.toNumber(),
{ metaPending: true, metaMined: false }
));
}

if (event === 'MetaChanged' && type === 'mined') {
setTimeout(() => {
dispatch(setTokenData(
params.id.toNumber(),
params.id.value.toNumber(),
{ metaPending: false, metaMined: false }
));
}, 5000);

return dispatch(setTokenData(
params.id.toNumber(),
params.id.value.toNumber(),
{ metaPending: false, metaMined: true }
));
}
Expand Down
183 changes: 183 additions & 0 deletions js/src/views/Contract/Events/Event/event.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

import BigNumber from 'bignumber.js';
import moment from 'moment';
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';

import { fetchBlock, fetchTransaction } from '../../../../redux/providers/blockchainActions';
import { IdentityIcon, IdentityName, Input, InputAddress } from '../../../../ui';

import styles from '../../contract.css';

class Event extends Component {
static contextTypes = {
api: PropTypes.object.isRequired
}

static propTypes = {
event: PropTypes.object.isRequired,
blocks: PropTypes.object,
transactions: PropTypes.object,
isTest: PropTypes.bool,
fetchBlock: PropTypes.func.isRequired,
fetchTransaction: PropTypes.func.isRequired
}

componentDidMount () {
this.retrieveTransaction();
}

render () {
const { event, blocks, transactions, isTest } = this.props;

const block = blocks[event.blockNumber.toString()];
const transaction = transactions[event.transactionHash] || {};
const classes = `${styles.event} ${styles[event.state]}`;
const url = `https://${isTest ? 'testnet.' : ''}etherscan.io/tx/${event.transactionHash}`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't we have this URL constructor more DRY ? If etherscan ever goes down, or change its URL structure, it would be good to only modify it in one place whether than in every component

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to log these seperately - think they are valid points, just not quite up to the task at exactly this point in time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const keys = Object.keys(event.params).join(', ');
const values = Object.keys(event.params).map((name, index) => {
const param = event.params[name];

return (
<div className={ styles.eventValue } key={ `${event.key}_val_${index}` }>
{ this.renderParam(name, param) }
</div>
);
});

return (
<tr className={ classes }>
<td className={ styles.timestamp }>
<div>{ event.state === 'pending' ? 'pending' : this.formatBlockTimestamp(block) }</div>
<div>{ this.formatNumber(transaction.blockNumber) }</div>
</td>
<td className={ styles.txhash }>
{ this.renderAddressName(transaction.from) }
</td>
<td className={ styles.txhash }>
<div className={ styles.eventType }>
{ event.type }({ keys })
</div>
<a href={ url } target='_blank'>{ this.formatHash(event.transactionHash) }</a>
</td>
<td className={ styles.eventDetails }>
<div className={ styles.eventParams }>
{ values }
</div>
</td>
</tr>
);
}

formatHash (hash) {
if (!hash || hash.length <= 16) {
return hash;
}

return `${hash.substr(2, 6)}...${hash.slice(-6)}`;
}

renderAddressName (address, withName = true) {
return (
<span className={ styles.eventAddress }>
<IdentityIcon center inline address={ address } className={ styles.eventIdentityicon } />
{ withName ? <IdentityName address={ address } /> : address }
</span>
);
}

renderParam (name, param) {
const { api } = this.context;

switch (param.type) {
case 'address':
return (
<InputAddress
disabled
text
className={ styles.input }
value={ param.value }
label={ name } />
);

default:
let value;
if (api.util.isInstanceOf(param.value, BigNumber)) {
value = param.value.toFormat(0);
} else if (api.util.isArray(param.value)) {
value = api.util.bytesToHex(param.value);
} else {
value = param.value.toString();
}

return (
<Input
disabled
className={ styles.input }
value={ value }
label={ name } />
);
}
}

formatBlockTimestamp (block) {
if (!block) {
return null;
}

return moment(block.timestamp).fromNow();
}

formatNumber (number) {
if (!number) {
return null;
}

return new BigNumber(number).toFormat();
}

retrieveTransaction () {
const { event, fetchBlock, fetchTransaction } = this.props;

fetchBlock(event.blockNumber);
fetchTransaction(event.transactionHash);
}
}

function mapStateToProps (state) {
const { isTest } = state.nodeStatus;
const { blocks, transactions } = state.blockchain;

return {
isTest,
blocks,
transactions
};
}

function mapDispatchToProps (dispatch) {
return bindActionCreators({
fetchBlock, fetchTransaction
}, dispatch);
}

export default connect(
mapStateToProps,
mapDispatchToProps
)(Event);
17 changes: 17 additions & 0 deletions js/src/views/Contract/Events/Event/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

export default from './event';
Loading