diff --git a/js/src/api/contract/contract.js b/js/src/api/contract/contract.js
index 40caa7643..cef75eda7 100644
--- a/js/src/api/contract/contract.js
+++ b/js/src/api/contract/contract.js
@@ -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;
diff --git a/js/src/dapps/basiccoin/Deploy/Events/events.js b/js/src/dapps/basiccoin/Deploy/Events/events.js
index a21672a8e..4b51afb59 100644
--- a/js/src/dapps/basiccoin/Deploy/Events/events.js
+++ b/js/src/dapps/basiccoin/Deploy/Events/events.js
@@ -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;
}
diff --git a/js/src/dapps/basiccoin/Transfer/Events/events.js b/js/src/dapps/basiccoin/Transfer/Events/events.js
index dcead03bb..101c77f73 100644
--- a/js/src/dapps/basiccoin/Transfer/Events/events.js
+++ b/js/src/dapps/basiccoin/Transfer/Events/events.js
@@ -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;
}
@@ -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 });
}
}
diff --git a/js/src/dapps/gavcoin/Events/events.js b/js/src/dapps/gavcoin/Events/events.js
index cb287b3a7..ba71d6541 100644
--- a/js/src/dapps/gavcoin/Events/events.js
+++ b/js/src/dapps/gavcoin/Events/events.js
@@ -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
};
};
diff --git a/js/src/dapps/registry/Events/events.js b/js/src/dapps/registry/Events/events.js
index ffb1fc919..10280ae52 100644
--- a/js/src/dapps/registry/Events/events.js
+++ b/js/src/dapps/registry/Events/events.js
@@ -48,9 +48,9 @@ const renderEvent = (classNames, verb) => (e, accounts, contacts) => {
return (
- { renderAddress(e.parameters.owner, accounts, contacts) }
+ { renderAddress(e.parameters.owner.value, accounts, contacts) }
{ verb }
- { renderHash(bytesToHex(e.parameters.name)) }
+ { renderHash(bytesToHex(e.parameters.name.value)) }
{ renderStatus(e.timestamp, e.state === 'pending') }
);
@@ -64,10 +64,10 @@ const renderDataChanged = (e, accounts, contacts) => {
return (
- { renderAddress(e.parameters.owner, accounts, contacts) }
+ { renderAddress(e.parameters.owner.value, accounts, contacts) }
updated
- key { new Buffer(e.parameters.plainKey).toString('utf8') }
of { renderHash(bytesToHex(e.parameters.name)) }
+ key { new Buffer(e.parameters.plainKey.value).toString('utf8') }
of { renderHash(bytesToHex(e.parameters.name.value)) }
{ renderStatus(e.timestamp, e.state === 'pending') }
diff --git a/js/src/dapps/signaturereg/services.js b/js/src/dapps/signaturereg/services.js
index 3942f75cc..7219ddff1 100644
--- a/js/src/dapps/signaturereg/services.js
+++ b/js/src/dapps/signaturereg/services.js
@@ -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
};
};
diff --git a/js/src/dapps/tokenreg/Status/actions.js b/js/src/dapps/tokenreg/Status/actions.js
index 9ec196aed..b7de9c108 100644
--- a/js/src/dapps/tokenreg/Status/actions.js
+++ b/js/src/dapps/tokenreg/Status/actions.js
@@ -148,27 +148,27 @@ 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 }
));
}
@@ -176,13 +176,13 @@ export const subscribeEvents = () => (dispatch, getState) => {
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 }
));
}
diff --git a/js/src/views/Contract/Events/Event/event.js b/js/src/views/Contract/Events/Event/event.js
new file mode 100644
index 000000000..cfe5be251
--- /dev/null
+++ b/js/src/views/Contract/Events/Event/event.js
@@ -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 .
+
+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}`;
+ const keys = Object.keys(event.params).join(', ');
+ const values = Object.keys(event.params).map((name, index) => {
+ const param = event.params[name];
+
+ return (
+
+ { this.renderParam(name, param) }
+
+ );
+ });
+
+ return (
+
+
+ { event.state === 'pending' ? 'pending' : this.formatBlockTimestamp(block) }
+ { this.formatNumber(transaction.blockNumber) }
+
+
+ { this.renderAddressName(transaction.from) }
+
+
+
+ { event.type }({ keys })
+
+ { this.formatHash(event.transactionHash) }
+
+
+
+ { values }
+
+
+
+ );
+ }
+
+ formatHash (hash) {
+ if (!hash || hash.length <= 16) {
+ return hash;
+ }
+
+ return `${hash.substr(2, 6)}...${hash.slice(-6)}`;
+ }
+
+ renderAddressName (address, withName = true) {
+ return (
+
+
+ { withName ? : address }
+
+ );
+ }
+
+ renderParam (name, param) {
+ const { api } = this.context;
+
+ switch (param.type) {
+ case 'address':
+ return (
+
+ );
+
+ 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 (
+
+ );
+ }
+ }
+
+ 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);
diff --git a/js/src/views/Contract/Events/Event/index.js b/js/src/views/Contract/Events/Event/index.js
new file mode 100644
index 000000000..0925882d3
--- /dev/null
+++ b/js/src/views/Contract/Events/Event/index.js
@@ -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 .
+
+export default from './event';
diff --git a/js/src/views/Contract/Events/events.js b/js/src/views/Contract/Events/events.js
index 7ff0341b3..0428a0ee3 100644
--- a/js/src/views/Contract/Events/events.js
+++ b/js/src/views/Contract/Events/events.js
@@ -14,11 +14,11 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see .
-import BigNumber from 'bignumber.js';
import React, { Component, PropTypes } from 'react';
import { Container, ContainerTitle } from '../../../ui';
+import Event from './Event';
import styles from '../contract.css';
export default class Events extends Component {
@@ -27,106 +27,23 @@ export default class Events extends Component {
}
static propTypes = {
- events: PropTypes.array,
- isTest: PropTypes.bool
- }
-
- state = {
- transactions: {}
- }
-
- componentDidMount () {
- this.componentWillReceiveProps(this.props);
- }
-
- componentWillReceiveProps (newProps) {
- this.retrieveTransactions(newProps.events);
+ events: PropTypes.array
}
render () {
- const { events, isTest } = this.props;
- const { transactions } = this.state;
+ const { events } = this.props;
if (!events || !events.length) {
return null;
}
- const rows = events.map((event) => {
- const transaction = transactions[event.transactionHash] || {};
- const classes = `${styles.event} ${styles[event.state]}`;
- const url = `https://${isTest ? 'testnet.' : ''}etherscan.io/tx/${event.transactionHash}`;
- const keys = Object.keys(event.params).map((key, index) => {
- return { key }
;
- });
- const values = Object.values(event.params).map((value, index) => {
- return (
-
- { this.renderValue(value) }
-
- );
- });
-
- return (
-
- { event.state === 'pending' ? 'pending' : event.blockNumber.toFormat(0) }
-
- { transaction.from }
- { event.transactionHash }
-
-
- { event.type } =>
- { keys }
-
-
-
- { values }
-
-
- );
- });
-
return (
- { rows }
+ { events.map((event) => ) }
);
}
-
- renderValue (value) {
- const { api } = this.context;
-
- if (api.util.isInstanceOf(value, BigNumber)) {
- return value.toFormat(0);
- } else if (api.util.isArray(value)) {
- return api.util.bytesToHex(value);
- }
-
- return value.toString();
- }
-
- retrieveTransactions (events) {
- const { api } = this.context;
- const { transactions } = this.state;
- const hashes = {};
-
- events.forEach((event) => {
- if (!hashes[event.transactionHash] && !transactions[event.transactionHash]) {
- hashes[event.transactionHash] = true;
- }
- });
-
- Promise
- .all(Object.keys(hashes).map((hash) => api.eth.getTransactionByHash(hash)))
- .then((newTransactions) => {
- this.setState({
- transactions: newTransactions.reduce((store, transaction) => {
- transactions[transaction.hash] = transaction;
- return transactions;
- }, transactions)
- });
- });
- }
}
diff --git a/js/src/views/Contract/contract.css b/js/src/views/Contract/contract.css
index 6956b8c50..4c6e93a3a 100644
--- a/js/src/views/Contract/contract.css
+++ b/js/src/views/Contract/contract.css
@@ -24,9 +24,12 @@
border-spacing: 0;
}
-.event {
+.events tr {
+ line-height: 32px;
vertical-align: top;
- line-height: 26px;
+}
+
+.event {
}
.event td {
@@ -43,9 +46,6 @@
color: #aaa;
}
-.value {
-}
-
.event td div {
white-space: nowrap;
}
@@ -56,3 +56,35 @@
.pending {
opacity: 0.5;
}
+
+.timestamp {
+ padding-top: 1.5em;
+ text-align: right;
+ line-height: 1.5em;
+ opacity: 0.5;
+ white-space: nowrap;
+}
+
+.eventDetails {
+}
+
+.eventType {
+}
+
+.eventParams {
+ padding-left: 2em;
+}
+
+.eventValue {
+ margin-top: -16px;
+}
+
+.eventAddress {
+ display: inline-block;
+ position: relative;
+}
+
+.eventIdentityicon {
+ margin-bottom: -10px;
+ margin-right: 0.5em;
+}
diff --git a/js/src/views/Contract/contract.js b/js/src/views/Contract/contract.js
index ec12c3ac9..394f8b360 100644
--- a/js/src/views/Contract/contract.js
+++ b/js/src/views/Contract/contract.js
@@ -116,7 +116,6 @@ class Contract extends Component {
contract={ contract }
values={ queryValues } />