Merge pull request #3671 from ethcore/jg-signer-decoding
Signer method parameter decoding & destination info
This commit is contained in:
commit
be7401c8bf
@ -44,9 +44,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.gasDetails {
|
.gasDetails {
|
||||||
padding-top: 1em;
|
padding-top: 0.75em;
|
||||||
font-size: 0.75em;
|
font-size: 0.75em;
|
||||||
line-height: 2em;
|
line-height: 1.5em;
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,16 +142,17 @@ class MethodDecoding extends Component {
|
|||||||
getAscii () {
|
getAscii () {
|
||||||
const { api } = this.context;
|
const { api } = this.context;
|
||||||
const { transaction } = this.props;
|
const { transaction } = this.props;
|
||||||
|
const ascii = api.util.hex2Ascii(transaction.input || transaction.data);
|
||||||
|
|
||||||
const ascii = api.util.hex2Ascii(transaction.input);
|
|
||||||
return { value: ascii, valid: ASCII_INPUT.test(ascii) };
|
return { value: ascii, valid: ASCII_INPUT.test(ascii) };
|
||||||
}
|
}
|
||||||
|
|
||||||
renderInputValue () {
|
renderInputValue () {
|
||||||
const { transaction } = this.props;
|
const { transaction } = this.props;
|
||||||
const { expandInput, inputType } = this.state;
|
const { expandInput, inputType } = this.state;
|
||||||
|
const input = transaction.input || transaction.data;
|
||||||
|
|
||||||
if (!/^(0x)?([0]*[1-9a-f]+[0]*)+$/.test(transaction.input)) {
|
if (!/^(0x)?([0]*[1-9a-f]+[0]*)+$/.test(input)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,7 +163,7 @@ class MethodDecoding extends Component {
|
|||||||
|
|
||||||
const text = type === 'ascii'
|
const text = type === 'ascii'
|
||||||
? ascii.value
|
? ascii.value
|
||||||
: transaction.input;
|
: input;
|
||||||
|
|
||||||
const expandable = text.length > 50;
|
const expandable = text.length > 50;
|
||||||
const textToShow = expandInput || !expandable
|
const textToShow = expandInput || !expandable
|
||||||
@ -447,11 +448,12 @@ class MethodDecoding extends Component {
|
|||||||
|
|
||||||
const isReceived = transaction.to === address;
|
const isReceived = transaction.to === address;
|
||||||
const contractAddress = isReceived ? transaction.from : transaction.to;
|
const contractAddress = isReceived ? transaction.from : transaction.to;
|
||||||
|
const input = transaction.input || transaction.data;
|
||||||
|
|
||||||
const token = (tokens || {})[contractAddress];
|
const token = (tokens || {})[contractAddress];
|
||||||
this.setState({ token, isReceived, contractAddress });
|
this.setState({ token, isReceived, contractAddress });
|
||||||
|
|
||||||
if (!transaction.input || transaction.input === '0x') {
|
if (!input || input === '0x') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -470,7 +472,7 @@ class MethodDecoding extends Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { signature, paramdata } = api.util.decodeCallData(transaction.input);
|
const { signature, paramdata } = api.util.decodeCallData(input);
|
||||||
this.setState({ methodSignature: signature, methodParams: paramdata });
|
this.setState({ methodSignature: signature, methodParams: paramdata });
|
||||||
|
|
||||||
if (!signature || signature === CONTRACT_CREATE || transaction.creates) {
|
if (!signature || signature === CONTRACT_CREATE || transaction.creates) {
|
||||||
|
@ -19,6 +19,6 @@ $pendingHeight: 190px;
|
|||||||
$finishedHeight: 120px;
|
$finishedHeight: 120px;
|
||||||
|
|
||||||
$embedWidth: 920px;
|
$embedWidth: 920px;
|
||||||
$statusWidth: 260px;
|
$statusWidth: 270px;
|
||||||
|
|
||||||
$accountPadding: 75px;
|
$accountPadding: 75px;
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
// 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 './requestFinished';
|
|
@ -1,87 +0,0 @@
|
|||||||
// 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 React, { Component, PropTypes } from 'react';
|
|
||||||
|
|
||||||
import TransactionFinished from '../TransactionFinished';
|
|
||||||
import SignRequest from '../SignRequest';
|
|
||||||
|
|
||||||
export default class RequestFinished extends Component {
|
|
||||||
static propTypes = {
|
|
||||||
id: PropTypes.object.isRequired,
|
|
||||||
result: PropTypes.any.isRequired,
|
|
||||||
date: PropTypes.instanceOf(Date).isRequired,
|
|
||||||
payload: PropTypes.oneOfType([
|
|
||||||
PropTypes.shape({ signTransaction: PropTypes.object.isRequired }),
|
|
||||||
PropTypes.shape({ sendTransaction: PropTypes.object.isRequired }),
|
|
||||||
PropTypes.shape({ sign: PropTypes.object.isRequired })
|
|
||||||
]).isRequired,
|
|
||||||
msg: PropTypes.string,
|
|
||||||
status: PropTypes.string,
|
|
||||||
error: PropTypes.string,
|
|
||||||
className: PropTypes.string,
|
|
||||||
isTest: PropTypes.bool.isRequired,
|
|
||||||
store: PropTypes.object.isRequired
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const { payload, id, result, msg, status, error, date, className, isTest, store } = this.props;
|
|
||||||
|
|
||||||
if (payload.sign) {
|
|
||||||
const { sign } = payload;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SignRequest
|
|
||||||
className={ className }
|
|
||||||
isFinished
|
|
||||||
id={ id }
|
|
||||||
address={ sign.address }
|
|
||||||
hash={ sign.hash }
|
|
||||||
msg={ msg }
|
|
||||||
status={ status }
|
|
||||||
error={ error }
|
|
||||||
isTest={ isTest }
|
|
||||||
store={ store }
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const transaction = payload.sendTransaction || payload.signTransaction;
|
|
||||||
if (transaction) {
|
|
||||||
return (
|
|
||||||
<TransactionFinished
|
|
||||||
className={ className }
|
|
||||||
txHash={ result }
|
|
||||||
id={ id }
|
|
||||||
gasPrice={ transaction.gasPrice }
|
|
||||||
gas={ transaction.gas }
|
|
||||||
from={ transaction.from }
|
|
||||||
to={ transaction.to }
|
|
||||||
value={ transaction.value }
|
|
||||||
msg={ msg }
|
|
||||||
date={ date }
|
|
||||||
status={ status }
|
|
||||||
error={ error }
|
|
||||||
isTest={ isTest }
|
|
||||||
store={ store }
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unknown payload
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -74,12 +74,7 @@ export default class RequestPending extends Component {
|
|||||||
onReject={ onReject }
|
onReject={ onReject }
|
||||||
isSending={ isSending }
|
isSending={ isSending }
|
||||||
id={ id }
|
id={ id }
|
||||||
gasPrice={ transaction.gasPrice }
|
transaction={ transaction }
|
||||||
gas={ transaction.gas }
|
|
||||||
data={ transaction.data }
|
|
||||||
from={ transaction.from }
|
|
||||||
to={ transaction.to }
|
|
||||||
value={ transaction.value }
|
|
||||||
date={ date }
|
date={ date }
|
||||||
isTest={ isTest }
|
isTest={ isTest }
|
||||||
store={ store }
|
store={ store }
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
/* 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 '../../_layout.css';
|
|
||||||
|
|
||||||
.container {
|
|
||||||
display: flex;
|
|
||||||
padding: 1.5em 0 1em;
|
|
||||||
|
|
||||||
& > * {
|
|
||||||
vertical-align: middle;
|
|
||||||
min-height: $finishedHeight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.statusContainer {
|
|
||||||
box-sizing: border-box;
|
|
||||||
float: right;
|
|
||||||
padding: 0 1em;
|
|
||||||
flex: 0 0 $statusWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
.transactionDetails {
|
|
||||||
width: 100%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.isConfirmed {
|
|
||||||
color: green;
|
|
||||||
}
|
|
||||||
|
|
||||||
.isRejected {
|
|
||||||
opacity: 0.5;
|
|
||||||
padding-top: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.txHash {
|
|
||||||
display: block;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
@ -1,120 +0,0 @@
|
|||||||
// 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 React, { Component, PropTypes } from 'react';
|
|
||||||
import { observer } from 'mobx-react';
|
|
||||||
|
|
||||||
import { TxHash } from '../../../../ui';
|
|
||||||
|
|
||||||
import TransactionMainDetails from '../TransactionMainDetails';
|
|
||||||
import TxHashLink from '../TxHashLink';
|
|
||||||
import TransactionSecondaryDetails from '../TransactionSecondaryDetails';
|
|
||||||
|
|
||||||
import styles from './TransactionFinished.css';
|
|
||||||
|
|
||||||
import * as tUtil from '../util/transaction';
|
|
||||||
import { capitalize } from '../util/util';
|
|
||||||
|
|
||||||
@observer
|
|
||||||
export default class TransactionFinished extends Component {
|
|
||||||
static propTypes = {
|
|
||||||
id: PropTypes.object.isRequired,
|
|
||||||
from: PropTypes.string.isRequired,
|
|
||||||
value: PropTypes.object.isRequired, // wei hex
|
|
||||||
gasPrice: PropTypes.object.isRequired, // wei hex
|
|
||||||
gas: PropTypes.object.isRequired, // hex
|
|
||||||
status: PropTypes.string.isRequired, // rejected, confirmed
|
|
||||||
date: PropTypes.instanceOf(Date).isRequired,
|
|
||||||
to: PropTypes.string, // undefined if it's a contract
|
|
||||||
txHash: PropTypes.string, // undefined if transacation is rejected
|
|
||||||
className: PropTypes.string,
|
|
||||||
data: PropTypes.string,
|
|
||||||
isTest: PropTypes.bool.isRequired,
|
|
||||||
store: PropTypes.object.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
componentWillMount () {
|
|
||||||
const { from, to, gas, gasPrice, value, store } = this.props;
|
|
||||||
const fee = tUtil.getFee(gas, gasPrice); // BigNumber object
|
|
||||||
const totalValue = tUtil.getTotalValue(fee, value);
|
|
||||||
|
|
||||||
this.setState({ totalValue });
|
|
||||||
store.fetchBalances([from, to]);
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const { className, date, id, from, to, store } = this.props;
|
|
||||||
|
|
||||||
const fromBalance = store.balances[from];
|
|
||||||
const toBalance = store.balances[to];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={ `${styles.container} ${className || ''}` }>
|
|
||||||
<TransactionMainDetails
|
|
||||||
{ ...this.props }
|
|
||||||
{ ...this.state }
|
|
||||||
fromBalance={ fromBalance }
|
|
||||||
toBalance={ toBalance }
|
|
||||||
className={ styles.transactionDetails }
|
|
||||||
>
|
|
||||||
<TransactionSecondaryDetails
|
|
||||||
id={ id }
|
|
||||||
date={ date }
|
|
||||||
/>
|
|
||||||
</TransactionMainDetails>
|
|
||||||
<div className={ styles.statusContainer }>
|
|
||||||
{ this.renderStatus() }
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderStatus () {
|
|
||||||
const { status, txHash } = this.props;
|
|
||||||
|
|
||||||
if (status !== 'confirmed') {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<span className={ styles.isRejected }>{ capitalize(status) }</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TxHash
|
|
||||||
summary
|
|
||||||
hash={ txHash } />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderTxHash () {
|
|
||||||
const { txHash, isTest } = this.props;
|
|
||||||
|
|
||||||
if (!txHash) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
Transaction hash:
|
|
||||||
<TxHashLink
|
|
||||||
isTest={ isTest }
|
|
||||||
txHash={ txHash }
|
|
||||||
className={ styles.txHash } />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
// 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 './TransactionFinished';
|
|
@ -30,27 +30,26 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.from, .to {
|
.from {
|
||||||
width: 50%;
|
width: 40%;
|
||||||
}
|
vertical-align: top;
|
||||||
|
|
||||||
.from .account {
|
img {
|
||||||
padding-right: $accountPadding;
|
|
||||||
}
|
|
||||||
|
|
||||||
.to .account {
|
|
||||||
padding-left: $accountPadding;
|
|
||||||
}
|
|
||||||
|
|
||||||
.from img, .to img {
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 50px;
|
width: 50px;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.from span, .to span {
|
.method {
|
||||||
display: block;
|
width: 60%;
|
||||||
|
vertical-align: top;
|
||||||
|
line-height: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tx {
|
.tx {
|
||||||
|
@ -16,9 +16,10 @@
|
|||||||
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
|
|
||||||
import ContractIcon from 'material-ui/svg-icons/action/code';
|
|
||||||
import ReactTooltip from 'react-tooltip';
|
import ReactTooltip from 'react-tooltip';
|
||||||
|
|
||||||
|
import { MethodDecoding } from '../../../../ui';
|
||||||
|
|
||||||
import * as tUtil from '../util/transaction';
|
import * as tUtil from '../util/transaction';
|
||||||
import Account from '../Account';
|
import Account from '../Account';
|
||||||
import styles from './TransactionMainDetails.css';
|
import styles from './TransactionMainDetails.css';
|
||||||
@ -31,8 +32,7 @@ export default class TransactionMainDetails extends Component {
|
|||||||
value: PropTypes.object.isRequired, // wei hex
|
value: PropTypes.object.isRequired, // wei hex
|
||||||
totalValue: PropTypes.object.isRequired, // wei BigNumber
|
totalValue: PropTypes.object.isRequired, // wei BigNumber
|
||||||
isTest: PropTypes.bool.isRequired,
|
isTest: PropTypes.bool.isRequired,
|
||||||
to: PropTypes.string, // undefined if it's a contract
|
transaction: PropTypes.object.isRequired,
|
||||||
toBalance: PropTypes.object, // eth BigNumber - undefined if it's a contract or until it's fetched
|
|
||||||
children: PropTypes.node
|
children: PropTypes.node
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -59,15 +59,7 @@ export default class TransactionMainDetails extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { to } = this.props;
|
const { children, from, fromBalance, transaction, isTest } = this.props;
|
||||||
|
|
||||||
return to
|
|
||||||
? this.renderTransfer()
|
|
||||||
: this.renderContract();
|
|
||||||
}
|
|
||||||
|
|
||||||
renderTransfer () {
|
|
||||||
const { children, from, fromBalance, to, toBalance, isTest } = this.props;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ styles.transaction }>
|
<div className={ styles.transaction }>
|
||||||
@ -79,48 +71,11 @@ export default class TransactionMainDetails extends Component {
|
|||||||
isTest={ isTest } />
|
isTest={ isTest } />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={ styles.tx }>
|
<div className={ styles.method }>
|
||||||
{ this.renderValue() }
|
<MethodDecoding
|
||||||
<div>⇒</div>
|
|
||||||
{ this.renderTotalValue() }
|
|
||||||
</div>
|
|
||||||
<div className={ styles.to }>
|
|
||||||
<div className={ styles.account }>
|
|
||||||
<Account
|
|
||||||
address={ to }
|
|
||||||
balance={ toBalance }
|
|
||||||
isTest={ isTest } />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{ children }
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderContract () {
|
|
||||||
const { children, from, fromBalance, isTest } = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={ styles.transaction }>
|
|
||||||
<div className={ styles.from }>
|
|
||||||
<div className={ styles.account }>
|
|
||||||
<Account
|
|
||||||
address={ from }
|
address={ from }
|
||||||
balance={ fromBalance }
|
transaction={ transaction }
|
||||||
isTest={ isTest } />
|
historic={ false } />
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className={ styles.tx }>
|
|
||||||
{ this.renderValue() }
|
|
||||||
<div>⇒</div>
|
|
||||||
{ this.renderTotalValue() }
|
|
||||||
</div>
|
|
||||||
<div className={ styles.to }>
|
|
||||||
<div className={ styles.account }>
|
|
||||||
<ContractIcon className={ styles.contractIcon } />
|
|
||||||
<br />
|
|
||||||
Contract
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{ children }
|
{ children }
|
||||||
</div>
|
</div>
|
||||||
|
@ -19,9 +19,13 @@
|
|||||||
|
|
||||||
.container {
|
.container {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 1.5em 0 1em;
|
padding: 1em 0 1em;
|
||||||
|
|
||||||
& > * {
|
& > * {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.container+.container {
|
||||||
|
padding-top: 2em;
|
||||||
|
}
|
||||||
|
@ -19,7 +19,6 @@ import { observer } from 'mobx-react';
|
|||||||
|
|
||||||
import TransactionMainDetails from '../TransactionMainDetails';
|
import TransactionMainDetails from '../TransactionMainDetails';
|
||||||
import TransactionPendingForm from '../TransactionPendingForm';
|
import TransactionPendingForm from '../TransactionPendingForm';
|
||||||
import TransactionSecondaryDetails from '../TransactionSecondaryDetails';
|
|
||||||
|
|
||||||
import styles from './TransactionPending.css';
|
import styles from './TransactionPending.css';
|
||||||
|
|
||||||
@ -29,13 +28,15 @@ import * as tUtil from '../util/transaction';
|
|||||||
export default class TransactionPending extends Component {
|
export default class TransactionPending extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
id: PropTypes.object.isRequired,
|
id: PropTypes.object.isRequired,
|
||||||
|
transaction: PropTypes.shape({
|
||||||
from: PropTypes.string.isRequired,
|
from: PropTypes.string.isRequired,
|
||||||
value: PropTypes.object.isRequired, // wei hex
|
value: PropTypes.object.isRequired, // wei hex
|
||||||
gasPrice: PropTypes.object.isRequired, // wei hex
|
gasPrice: PropTypes.object.isRequired, // wei hex
|
||||||
gas: PropTypes.object.isRequired, // hex
|
gas: PropTypes.object.isRequired, // hex
|
||||||
date: PropTypes.instanceOf(Date).isRequired,
|
|
||||||
to: PropTypes.string, // undefined if it's a contract
|
|
||||||
data: PropTypes.string, // hex
|
data: PropTypes.string, // hex
|
||||||
|
to: PropTypes.string // undefined if it's a contract
|
||||||
|
}).isRequired,
|
||||||
|
date: PropTypes.instanceOf(Date).isRequired,
|
||||||
nonce: PropTypes.number,
|
nonce: PropTypes.number,
|
||||||
onConfirm: PropTypes.func.isRequired,
|
onConfirm: PropTypes.func.isRequired,
|
||||||
onReject: PropTypes.func.isRequired,
|
onReject: PropTypes.func.isRequired,
|
||||||
@ -50,7 +51,8 @@ export default class TransactionPending extends Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
componentWillMount () {
|
componentWillMount () {
|
||||||
const { gas, gasPrice, value, from, to, store } = this.props;
|
const { transaction, store } = this.props;
|
||||||
|
const { gas, gasPrice, value, from, to } = transaction;
|
||||||
|
|
||||||
const fee = tUtil.getFee(gas, gasPrice); // BigNumber object
|
const fee = tUtil.getFee(gas, gasPrice); // BigNumber object
|
||||||
const totalValue = tUtil.getTotalValue(fee, value);
|
const totalValue = tUtil.getTotalValue(fee, value);
|
||||||
@ -62,29 +64,22 @@ export default class TransactionPending extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { className, id, date, data, from, to, store } = this.props;
|
const { className, id, transaction, store } = this.props;
|
||||||
const { totalValue, gasPriceEthmDisplay, gasToDisplay } = this.state;
|
const { from, value } = transaction;
|
||||||
|
const { totalValue } = this.state;
|
||||||
|
|
||||||
const fromBalance = store.balances[from];
|
const fromBalance = store.balances[from];
|
||||||
const toBalance = store.balances[to];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ `${styles.container} ${className || ''}` }>
|
<div className={ `${styles.container} ${className || ''}` }>
|
||||||
<TransactionMainDetails
|
<TransactionMainDetails
|
||||||
{ ...this.props }
|
|
||||||
{ ...this.state }
|
|
||||||
fromBalance={ fromBalance }
|
|
||||||
toBalance={ toBalance }
|
|
||||||
className={ styles.transactionDetails }
|
|
||||||
totalValue={ totalValue }>
|
|
||||||
<TransactionSecondaryDetails
|
|
||||||
id={ id }
|
id={ id }
|
||||||
date={ date }
|
value={ value }
|
||||||
data={ data }
|
from={ from }
|
||||||
gasPriceEthmDisplay={ gasPriceEthmDisplay }
|
fromBalance={ fromBalance }
|
||||||
gasToDisplay={ gasToDisplay }
|
className={ styles.transactionDetails }
|
||||||
/>
|
transaction={ transaction }
|
||||||
</TransactionMainDetails>
|
totalValue={ totalValue } />
|
||||||
<TransactionPendingForm
|
<TransactionPendingForm
|
||||||
address={ from }
|
address={ from }
|
||||||
isSending={ this.props.isSending }
|
isSending={ this.props.isSending }
|
||||||
@ -96,7 +91,8 @@ export default class TransactionPending extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onConfirm = data => {
|
onConfirm = data => {
|
||||||
const { id, gasPrice } = this.props;
|
const { id, transaction } = this.props;
|
||||||
|
const { gasPrice } = transaction;
|
||||||
const { password, wallet } = data;
|
const { password, wallet } = data;
|
||||||
|
|
||||||
this.props.onConfirm({ id, password, wallet, gasPrice });
|
this.props.onConfirm({ id, password, wallet, gasPrice });
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
.container {
|
.container {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 1em 1em 0 1em;
|
padding: 1em 0 0 2em;
|
||||||
flex: 0 0 $statusWidth;
|
flex: 0 0 $statusWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,90 +0,0 @@
|
|||||||
/* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.container {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.iconsContainer {
|
|
||||||
display: block;
|
|
||||||
text-align: center;
|
|
||||||
font-size: .8em;
|
|
||||||
opacity: 0.5;
|
|
||||||
padding: 1em 0 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.iconsContainer > * {
|
|
||||||
margin-right: 3px;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.iconsContainer:after {
|
|
||||||
clear: both;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hasInfoIcon svg,
|
|
||||||
.miningTime svg,
|
|
||||||
.gasPrice svg,
|
|
||||||
.data svg,
|
|
||||||
.date svg {
|
|
||||||
width: 16px !important;
|
|
||||||
height: 16px !important;
|
|
||||||
position: relative;
|
|
||||||
bottom: -3px;
|
|
||||||
margin: 0 0.25rem 0 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO [ToDr] composes was handling weird errors when linking from other app */
|
|
||||||
.miningTime {
|
|
||||||
/* composes: hasInfoIcon; */
|
|
||||||
}
|
|
||||||
|
|
||||||
.gasPrice {
|
|
||||||
/* composes: hasInfoIcon; */
|
|
||||||
}
|
|
||||||
|
|
||||||
.data {
|
|
||||||
/* composes: hasInfoIcon; */
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.data.noData {
|
|
||||||
cursor: text;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.dataTooltip {
|
|
||||||
word-wrap: break-word;
|
|
||||||
max-width: 400px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.expandedData {
|
|
||||||
display: block;
|
|
||||||
padding: 15px;
|
|
||||||
background: gray;
|
|
||||||
word-wrap: break-word;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.expandedContainer {
|
|
||||||
padding: 10px;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.expandedContainer:empty {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
@ -1,178 +0,0 @@
|
|||||||
// 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 React, { Component, PropTypes } from 'react';
|
|
||||||
|
|
||||||
import ReactTooltip from 'react-tooltip';
|
|
||||||
import DescriptionIcon from 'material-ui/svg-icons/action/description';
|
|
||||||
import GasIcon from 'material-ui/svg-icons/maps/local-gas-station';
|
|
||||||
import TimeIcon from 'material-ui/svg-icons/device/access-time';
|
|
||||||
import moment from 'moment';
|
|
||||||
|
|
||||||
import styles from './TransactionSecondaryDetails.css';
|
|
||||||
|
|
||||||
import * as tUtil from '../util/transaction';
|
|
||||||
|
|
||||||
export default class TransactionSecondaryDetails extends Component {
|
|
||||||
static propTypes = {
|
|
||||||
id: PropTypes.object.isRequired,
|
|
||||||
date: PropTypes.instanceOf(Date),
|
|
||||||
data: PropTypes.string, // hex
|
|
||||||
gasPriceEthmDisplay: PropTypes.string,
|
|
||||||
gasToDisplay: PropTypes.string,
|
|
||||||
className: PropTypes.string
|
|
||||||
};
|
|
||||||
|
|
||||||
state = {
|
|
||||||
isDataExpanded: false
|
|
||||||
};
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const className = this.props.className || '';
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={ `${styles.container} ${className}` }>
|
|
||||||
<div className={ styles.iconsContainer }>
|
|
||||||
{ this.renderGasPrice() }
|
|
||||||
{ this.renderData() }
|
|
||||||
{ this.renderDate() }
|
|
||||||
</div>
|
|
||||||
<div className={ styles.expandedContainer }>
|
|
||||||
{ this.renderDataExpanded() }
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderGasPrice () {
|
|
||||||
if (!this.props.gasPriceEthmDisplay && !this.props.gasToDisplay) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { id } = this.props;
|
|
||||||
const { gasPriceEthmDisplay, gasToDisplay } = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
data-tip
|
|
||||||
data-place='right'
|
|
||||||
data-for={ 'gasPrice' + id }
|
|
||||||
data-effect='solid'
|
|
||||||
>
|
|
||||||
<span className={ styles.gasPrice }>
|
|
||||||
<GasIcon />
|
|
||||||
{ gasPriceEthmDisplay } <small>ETH/MGAS</small>
|
|
||||||
</span>
|
|
||||||
{ /* dynamic id required in case there are multple transactions in page */ }
|
|
||||||
<ReactTooltip id={ 'gasPrice' + id }>
|
|
||||||
Cost of 1,000,000 units of gas. This transaction will use up to <strong>{ gasToDisplay }</strong> <small>MGAS</small>.
|
|
||||||
</ReactTooltip>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderData () {
|
|
||||||
if (!this.props.data) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { data, id } = this.props;
|
|
||||||
let dataToDisplay = this.noData() ? 'no data' : tUtil.getShortData(data);
|
|
||||||
const noDataClass = this.noData() ? styles.noData : '';
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={ `${styles.data} ${noDataClass}` }
|
|
||||||
onClick={ this.toggleDataExpanded }
|
|
||||||
data-tip
|
|
||||||
data-place='right'
|
|
||||||
data-for={ 'data' + id }
|
|
||||||
data-class={ styles.dataTooltip }
|
|
||||||
data-effect='solid'
|
|
||||||
>
|
|
||||||
<DescriptionIcon />
|
|
||||||
{ dataToDisplay }
|
|
||||||
{ /* dynamic id required in case there are multple transactions in page */ }
|
|
||||||
<ReactTooltip id={ 'data' + id }>
|
|
||||||
<strong>Extra data for the transaction: </strong>
|
|
||||||
<br />
|
|
||||||
{ dataToDisplay }.
|
|
||||||
<br />
|
|
||||||
{ this.noData() ? '' : <strong>Click to expand.</strong> }
|
|
||||||
</ReactTooltip>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderDate () {
|
|
||||||
const { date, id } = this.props;
|
|
||||||
|
|
||||||
const dateToDisplay = moment(date).fromNow();
|
|
||||||
const fullDate = moment(date).format('LL LTS');
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={ styles.date }
|
|
||||||
data-tip
|
|
||||||
data-place='right'
|
|
||||||
data-for={ 'date' + id }
|
|
||||||
data-class={ styles.dataTooltip }
|
|
||||||
data-effect='solid'
|
|
||||||
>
|
|
||||||
<TimeIcon />
|
|
||||||
{ dateToDisplay }
|
|
||||||
{ /* dynamic id required in case there are multple transactions in page */ }
|
|
||||||
<ReactTooltip id={ 'date' + id }>
|
|
||||||
<strong>Date of the request: </strong>
|
|
||||||
<br />
|
|
||||||
{ fullDate }
|
|
||||||
</ReactTooltip>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderDataExpanded () {
|
|
||||||
if (!this.props.data) return null;
|
|
||||||
|
|
||||||
const { isDataExpanded } = this.state;
|
|
||||||
const { data } = this.props;
|
|
||||||
|
|
||||||
if (!isDataExpanded) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={ styles.expandedHelper }>
|
|
||||||
<h3>Transaction's Data</h3>
|
|
||||||
<code className={ styles.expandedData }>{ data }</code>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
noData () {
|
|
||||||
return this.props.data === '0x';
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleDataExpanded = () => {
|
|
||||||
if (this.noData()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.setState({
|
|
||||||
isDataExpanded: !this.state.isDataExpanded
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
export default from './TransactionSecondaryDetails';
|
|
@ -1,18 +0,0 @@
|
|||||||
// 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 RequestFinished from './RequestFinished';
|
|
||||||
export RequestPending from './RequestPending';
|
|
@ -23,7 +23,7 @@ import Store from '../../store';
|
|||||||
import * as RequestsActions from '../../../../redux/providers/signerActions';
|
import * as RequestsActions from '../../../../redux/providers/signerActions';
|
||||||
import { Container } from '../../../../ui';
|
import { Container } from '../../../../ui';
|
||||||
|
|
||||||
import { RequestPending } from '../../components';
|
import RequestPending from '../../components/RequestPending';
|
||||||
|
|
||||||
import styles from './embedded.css';
|
import styles from './embedded.css';
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ import Store from '../../store';
|
|||||||
import * as RequestsActions from '../../../../redux/providers/signerActions';
|
import * as RequestsActions from '../../../../redux/providers/signerActions';
|
||||||
import { Container, Page, TxList } from '../../../../ui';
|
import { Container, Page, TxList } from '../../../../ui';
|
||||||
|
|
||||||
import { RequestPending, RequestFinished } from '../../components';
|
import RequestPending from '../../components/RequestPending';
|
||||||
|
|
||||||
import styles from './RequestsPage.css';
|
import styles from './RequestsPage.css';
|
||||||
|
|
||||||
@ -57,7 +57,6 @@ class RequestsPage extends Component {
|
|||||||
<Page>
|
<Page>
|
||||||
<div>{ this.renderPendingRequests() }</div>
|
<div>{ this.renderPendingRequests() }</div>
|
||||||
<div>{ this.renderLocalQueue() }</div>
|
<div>{ this.renderLocalQueue() }</div>
|
||||||
<div>{ this.renderFinishedRequests() }</div>
|
|
||||||
</Page>
|
</Page>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -106,24 +105,6 @@ class RequestsPage extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderFinishedRequests () {
|
|
||||||
const { finished } = this.props.signer;
|
|
||||||
|
|
||||||
if (!finished.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const items = finished.sort(this._sortRequests).map(this.renderFinished);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Container title='Finished Requests'>
|
|
||||||
<div className={ styles.items }>
|
|
||||||
{ items }
|
|
||||||
</div>
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderPending = (data) => {
|
renderPending = (data) => {
|
||||||
const { actions, isTest } = this.props;
|
const { actions, isTest } = this.props;
|
||||||
const { payload, id, isSending, date } = data;
|
const { payload, id, isSending, date } = data;
|
||||||
@ -143,27 +124,6 @@ class RequestsPage extends Component {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderFinished = (data) => {
|
|
||||||
const { isTest } = this.props;
|
|
||||||
const { payload, id, result, msg, status, error, date } = data;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<RequestFinished
|
|
||||||
className={ styles.request }
|
|
||||||
result={ result }
|
|
||||||
key={ id }
|
|
||||||
id={ id }
|
|
||||||
msg={ msg }
|
|
||||||
status={ status }
|
|
||||||
error={ error }
|
|
||||||
payload={ payload }
|
|
||||||
date={ date }
|
|
||||||
isTest={ isTest }
|
|
||||||
store={ this.store }
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
|
Loading…
Reference in New Issue
Block a user