diff --git a/js/src/ui/TxHash/txHash.js b/js/src/ui/TxHash/txHash.js
index c054dc01fae..724004ae74f 100644
--- a/js/src/ui/TxHash/txHash.js
+++ b/js/src/ui/TxHash/txHash.js
@@ -1,4 +1,4 @@
-// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
+// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
@@ -21,8 +21,10 @@ import { FormattedMessage } from 'react-intl';
import { connect } from 'react-redux';
import { txLink } from '~/3rdparty/etherscan/links';
-import ShortenedHash from '../ShortenedHash';
+import Warning from '~/ui/Warning';
+import { DEFAULT_GAS } from '~/util/constants';
+import ShortenedHash from '../ShortenedHash';
import styles from './txHash.css';
class TxHash extends Component {
@@ -43,8 +45,59 @@ class TxHash extends Component {
state = {
blockNumber: new BigNumber(0),
+ isRecipientContract: false,
subscriptionId: null,
- transaction: null
+ transaction: null,
+ transactionReceipt: null
+ }
+
+ componentWillMount () {
+ this.fetchTransaction();
+ }
+
+ componentWillReceiveProps (nextProps) {
+ const prevHash = this.props.hash;
+ const nextHash = nextProps.hash;
+
+ if (prevHash !== nextHash) {
+ this.fetchTransaction(nextProps);
+ }
+ }
+
+ /**
+ * Get the sent transaction data
+ */
+ fetchTransaction (props = this.props) {
+ const { hash } = props;
+
+ if (!hash) {
+ return;
+ }
+
+ this.context.api.eth
+ .getTransactionByHash(hash)
+ .then((transaction) => {
+ this.setState({ transaction });
+
+ return this.fetchRecipientCode(transaction);
+ });
+ }
+
+ fetchRecipientCode (transaction) {
+ if (!transaction || !transaction.to) {
+ return;
+ }
+
+ this.context.api.eth
+ .getCode(transaction.to)
+ .then((code) => {
+ const isRecipientContract = code && !/^(0x)?0*$/.test(code);
+
+ this.setState({ isRecipientContract });
+ })
+ .catch((error) => {
+ console.error('fetchRecipientCode', error);
+ });
}
componentDidMount () {
@@ -73,24 +126,58 @@ class TxHash extends Component {
return (
+ { this.renderWarning() }
{
summary
? hashLink
:
+ values={ { hashLink } }
+ />
}
{ this.renderConfirmations() }
);
}
+ renderWarning () {
+ const { isRecipientContract, transaction, transactionReceipt } = this.state;
+
+ if (!(transactionReceipt && transactionReceipt.blockNumber && transactionReceipt.blockNumber.gt(0))) {
+ return null;
+ }
+
+ const { gas, input } = transaction;
+ const { gasUsed = new BigNumber(0) } = transactionReceipt;
+
+ const isOog = gasUsed.gte(gas);
+
+ // Skip OOG check if a simple transaction to a non-contract account
+ // @see: https://github.com/ethcore/parity/issues/4550
+ const skipOogCheck = gasUsed.eq(DEFAULT_GAS) && (!input || input === '0x') && !isRecipientContract;
+
+ if (!isOog || skipOogCheck) {
+ return null;
+ }
+
+ return (
+
+ }
+ />
+ );
+ }
+
renderConfirmations () {
const { maxConfirmations } = this.props;
- const { blockNumber, transaction } = this.state;
+ const { blockNumber, transactionReceipt } = this.state;
- if (!(transaction && transaction.blockNumber && transaction.blockNumber.gt(0))) {
+ if (!(transactionReceipt && transactionReceipt.blockNumber && transactionReceipt.blockNumber.gt(0))) {
return (
+ defaultMessage='waiting for confirmations'
+ />
);
}
- const confirmations = blockNumber.minus(transaction.blockNumber).plus(1);
+ const confirmations = blockNumber.minus(transactionReceipt.blockNumber).plus(1);
const value = Math.min(confirmations.toNumber(), maxConfirmations);
let count = confirmations.toFormat(0);
+
if (confirmations.lte(maxConfirmations)) {
count = `${count}/${maxConfirmations}`;
}
@@ -123,7 +212,8 @@ class TxHash extends Component {
max={ maxConfirmations }
value={ value }
color='white'
- mode='determinate' />
+ mode='determinate'
+ />
@@ -143,21 +234,22 @@ class TxHash extends Component {
const { api } = this.context;
const { hash } = this.props;
+ const nextState = { blockNumber };
+
if (error || !hash || /^(0x)?0*$/.test(hash)) {
- return;
+ return this.setState(nextState);
}
return api.eth
.getTransactionReceipt(hash)
- .then((transaction) => {
- this.setState({
- blockNumber,
- transaction
- });
+ .then((transactionReceipt) => {
+ nextState.transactionReceipt = transactionReceipt;
})
.catch((error) => {
- console.warn('onBlockNumber', error);
- this.setState({ blockNumber });
+ console.error('onBlockNumber', error);
+ })
+ .then(() => {
+ this.setState(nextState);
});
}
}