Fix wallet view (#6597)
* Add safe fail for empty logs * Filter transactions * Add more logging * Fix Wallet Creation and wallet tx list * Remove logs * Prevent selecting twice same wallet owner * Fix tests * Remove unused props * Remove unused props
This commit is contained in:
parent
65ca2f9a07
commit
8d1964bc3b
@ -16,18 +16,21 @@
|
|||||||
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { Form, TypedInput, Input, AddressSelect, InputAddress } from '~/ui';
|
import { Form, TypedInput, Input, AddressSelect, InputAddress } from '~/ui';
|
||||||
|
|
||||||
import styles from '../createWallet.css';
|
import styles from '../createWallet.css';
|
||||||
|
|
||||||
export default class WalletDetails extends Component {
|
class WalletDetails extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
accounts: PropTypes.object.isRequired,
|
accounts: PropTypes.object.isRequired,
|
||||||
wallet: PropTypes.object.isRequired,
|
wallet: PropTypes.object.isRequired,
|
||||||
errors: PropTypes.object.isRequired,
|
errors: PropTypes.object.isRequired,
|
||||||
onChange: PropTypes.func.isRequired,
|
onChange: PropTypes.func.isRequired,
|
||||||
walletType: PropTypes.string.isRequired
|
walletType: PropTypes.string.isRequired,
|
||||||
|
|
||||||
|
knownAddresses: PropTypes.array
|
||||||
};
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
@ -103,7 +106,10 @@ export default class WalletDetails extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderMultisigDetails () {
|
renderMultisigDetails () {
|
||||||
const { accounts, wallet, errors } = this.props;
|
const { accounts, knownAddresses, wallet, errors } = this.props;
|
||||||
|
const allowedOwners = knownAddresses
|
||||||
|
// Exclude sender and already owners of the wallet
|
||||||
|
.filter((address) => !wallet.owners.includes(address) && address !== wallet.account);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form>
|
<Form>
|
||||||
@ -163,7 +169,7 @@ export default class WalletDetails extends Component {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<TypedInput
|
<TypedInput
|
||||||
accounts={ accounts }
|
allowedValues={ allowedOwners }
|
||||||
label={
|
label={
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='createWallet.details.ownersMulti.label'
|
id='createWallet.details.ownersMulti.label'
|
||||||
@ -249,3 +255,21 @@ export default class WalletDetails extends Component {
|
|||||||
this.props.onChange({ daylimit });
|
this.props.onChange({ daylimit });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mapStateToProps (initState) {
|
||||||
|
const { accounts, contacts, contracts } = initState.personal;
|
||||||
|
const knownAddresses = [].concat(
|
||||||
|
Object.keys(accounts),
|
||||||
|
Object.keys(contacts),
|
||||||
|
Object.keys(contracts)
|
||||||
|
);
|
||||||
|
|
||||||
|
return () => ({
|
||||||
|
knownAddresses
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
null
|
||||||
|
)(WalletDetails);
|
||||||
|
@ -25,6 +25,22 @@ import { ACCOUNTS } from '../createWallet.test.js';
|
|||||||
let component;
|
let component;
|
||||||
let onChange;
|
let onChange;
|
||||||
|
|
||||||
|
function createRedux () {
|
||||||
|
return {
|
||||||
|
dispatch: sinon.stub(),
|
||||||
|
subscribe: sinon.stub(),
|
||||||
|
getState: () => {
|
||||||
|
return {
|
||||||
|
personal: {
|
||||||
|
accounts: {},
|
||||||
|
contacts: {},
|
||||||
|
contracts: {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function render (walletType = 'MULTISIG') {
|
function render (walletType = 'MULTISIG') {
|
||||||
onChange = sinon.stub();
|
onChange = sinon.stub();
|
||||||
component = shallow(
|
component = shallow(
|
||||||
@ -36,7 +52,12 @@ function render (walletType = 'MULTISIG') {
|
|||||||
owners: []
|
owners: []
|
||||||
} }
|
} }
|
||||||
walletType={ walletType }
|
walletType={ walletType }
|
||||||
/>
|
/>,
|
||||||
|
{
|
||||||
|
context: {
|
||||||
|
store: createRedux()
|
||||||
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return component;
|
return component;
|
||||||
|
@ -283,7 +283,8 @@ export default class CreateWalletStore {
|
|||||||
|
|
||||||
const owners = _wallet.owners.filter((owner) => !/^(0x)?0*$/.test(owner));
|
const owners = _wallet.owners.filter((owner) => !/^(0x)?0*$/.test(owner));
|
||||||
|
|
||||||
if (_wallet.required > owners.length) {
|
// Real number of owners is owners + creator
|
||||||
|
if (_wallet.required > owners.length + 1) {
|
||||||
requiredValidation.valueError = 'the number of required validators should be lower or equal the number of owners';
|
requiredValidation.valueError = 'the number of required validators should be lower or equal the number of owners';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,6 @@ export default class ParametersStep extends Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
accounts: PropTypes.object.isRequired,
|
|
||||||
onParamsChange: PropTypes.func.isRequired,
|
onParamsChange: PropTypes.func.isRequired,
|
||||||
|
|
||||||
inputs: PropTypes.array,
|
inputs: PropTypes.array,
|
||||||
@ -60,7 +59,7 @@ export default class ParametersStep extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderConstructorInputs () {
|
renderConstructorInputs () {
|
||||||
const { accounts, params, paramsError } = this.props;
|
const { params, paramsError } = this.props;
|
||||||
const { inputs } = this.props;
|
const { inputs } = this.props;
|
||||||
|
|
||||||
if (!inputs || !inputs.length) {
|
if (!inputs || !inputs.length) {
|
||||||
@ -78,7 +77,6 @@ export default class ParametersStep extends Component {
|
|||||||
return (
|
return (
|
||||||
<div key={ index } className={ styles.funcparams }>
|
<div key={ index } className={ styles.funcparams }>
|
||||||
<TypedInput
|
<TypedInput
|
||||||
accounts={ accounts }
|
|
||||||
error={ error }
|
error={ error }
|
||||||
isEth={ false }
|
isEth={ false }
|
||||||
label={ label }
|
label={ label }
|
||||||
|
@ -314,7 +314,6 @@ class DeployContract extends Component {
|
|||||||
return (
|
return (
|
||||||
<ParametersStep
|
<ParametersStep
|
||||||
{ ...this.state }
|
{ ...this.state }
|
||||||
accounts={ accounts }
|
|
||||||
onParamsChange={ this.onParamsChange }
|
onParamsChange={ this.onParamsChange }
|
||||||
readOnly={ readOnly }
|
readOnly={ readOnly }
|
||||||
/>
|
/>
|
||||||
|
@ -177,7 +177,7 @@ export default class DetailsStep extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderParameters () {
|
renderParameters () {
|
||||||
const { accounts, func, values, valuesError, onValueChange } = this.props;
|
const { func, values, valuesError, onValueChange } = this.props;
|
||||||
|
|
||||||
if (!func) {
|
if (!func) {
|
||||||
return null;
|
return null;
|
||||||
@ -197,7 +197,6 @@ export default class DetailsStep extends Component {
|
|||||||
value={ values[index] }
|
value={ values[index] }
|
||||||
error={ valuesError[index] }
|
error={ valuesError[index] }
|
||||||
onChange={ onChange }
|
onChange={ onChange }
|
||||||
accounts={ accounts }
|
|
||||||
param={ input.type }
|
param={ input.type }
|
||||||
isEth={ false }
|
isEth={ false }
|
||||||
/>
|
/>
|
||||||
|
@ -34,7 +34,6 @@ class WalletSettings extends Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
accountsInfo: PropTypes.object.isRequired,
|
|
||||||
wallet: PropTypes.object.isRequired,
|
wallet: PropTypes.object.isRequired,
|
||||||
onClose: PropTypes.func.isRequired,
|
onClose: PropTypes.func.isRequired,
|
||||||
senders: PropTypes.object.isRequired
|
senders: PropTypes.object.isRequired
|
||||||
@ -74,7 +73,7 @@ class WalletSettings extends Component {
|
|||||||
default:
|
default:
|
||||||
case 'EDIT':
|
case 'EDIT':
|
||||||
const { errors, fromString, wallet } = this.store;
|
const { errors, fromString, wallet } = this.store;
|
||||||
const { accountsInfo, senders } = this.props;
|
const { senders } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form>
|
<Form>
|
||||||
@ -143,7 +142,6 @@ class WalletSettings extends Component {
|
|||||||
}
|
}
|
||||||
value={ wallet.owners.slice() }
|
value={ wallet.owners.slice() }
|
||||||
onChange={ this.store.onOwnersChange }
|
onChange={ this.store.onOwnersChange }
|
||||||
accounts={ accountsInfo }
|
|
||||||
param='address[]'
|
param='address[]'
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@ -443,13 +441,13 @@ class WalletSettings extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps (initState, initProps) {
|
function mapStateToProps (initState, initProps) {
|
||||||
const { accountsInfo, accounts } = initState.personal;
|
const { accounts } = initState.personal;
|
||||||
const { owners } = initProps.wallet;
|
const { owners } = initProps.wallet;
|
||||||
|
|
||||||
const senders = pick(accounts, owners);
|
const senders = pick(accounts, owners);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
return { accountsInfo, senders };
|
return { senders };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
// 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 { eq } from 'lodash';
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
@ -93,6 +94,18 @@ class AddressSelect extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps (nextProps) {
|
componentWillReceiveProps (nextProps) {
|
||||||
|
if (!eq(Object.keys(this.props.accounts), Object.keys(nextProps.accounts))) {
|
||||||
|
return this.setValues(nextProps);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!eq(Object.keys(this.props.contacts), Object.keys(nextProps.contacts))) {
|
||||||
|
return this.setValues(nextProps);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!eq(Object.keys(this.props.contracts), Object.keys(nextProps.contracts))) {
|
||||||
|
return this.setValues(nextProps);
|
||||||
|
}
|
||||||
|
|
||||||
if (this.store.values && this.store.values.length > 0) {
|
if (this.store.values && this.store.values.length > 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,8 @@ export default class AddressSelectStore {
|
|||||||
const contactsN = Object.keys(contacts).length;
|
const contactsN = Object.keys(contacts).length;
|
||||||
|
|
||||||
if (accountsN + contractsN + contactsN === 0) {
|
if (accountsN + contractsN + contactsN === 0) {
|
||||||
return;
|
this.initValues = [];
|
||||||
|
return this.handleChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.initValues = [
|
this.initValues = [
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
// 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 { pick } from 'lodash';
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
@ -28,6 +29,7 @@ class InputAddressSelect extends Component {
|
|||||||
contracts: PropTypes.object.isRequired,
|
contracts: PropTypes.object.isRequired,
|
||||||
|
|
||||||
allowCopy: PropTypes.bool,
|
allowCopy: PropTypes.bool,
|
||||||
|
allowedValues: PropTypes.array,
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
error: nodeOrStringProptype(),
|
error: nodeOrStringProptype(),
|
||||||
hint: nodeOrStringProptype(),
|
hint: nodeOrStringProptype(),
|
||||||
@ -38,16 +40,33 @@ class InputAddressSelect extends Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { accounts, allowCopy, className, contacts, contracts, label, hint, error, value, onChange, readOnly } = this.props;
|
const { accounts, allowCopy, allowedValues, className, contacts, contracts, label, hint, error, value, onChange, readOnly } = this.props;
|
||||||
|
// Add the currently selected value to the list
|
||||||
|
// of allowed values, if any given
|
||||||
|
const nextAllowedValues = allowedValues
|
||||||
|
? [].concat(allowedValues, value || [])
|
||||||
|
: null;
|
||||||
|
|
||||||
|
const filteredAccounts = nextAllowedValues
|
||||||
|
? pick(accounts, nextAllowedValues)
|
||||||
|
: accounts;
|
||||||
|
|
||||||
|
const filteredContacts = nextAllowedValues
|
||||||
|
? pick(contacts, nextAllowedValues)
|
||||||
|
: accounts;
|
||||||
|
|
||||||
|
const filteredContracts = nextAllowedValues
|
||||||
|
? pick(contracts, nextAllowedValues)
|
||||||
|
: accounts;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AddressSelect
|
<AddressSelect
|
||||||
allowCopy={ allowCopy }
|
allowCopy={ allowCopy }
|
||||||
allowInput
|
allowInput
|
||||||
accounts={ accounts }
|
accounts={ filteredAccounts }
|
||||||
className={ className }
|
className={ className }
|
||||||
contacts={ contacts }
|
contacts={ filteredContacts }
|
||||||
contracts={ contracts }
|
contracts={ filteredContracts }
|
||||||
error={ error }
|
error={ error }
|
||||||
hint={ hint }
|
hint={ hint }
|
||||||
label={ label }
|
label={ label }
|
||||||
|
@ -40,8 +40,8 @@ export default class TypedInput extends Component {
|
|||||||
PropTypes.string
|
PropTypes.string
|
||||||
]).isRequired,
|
]).isRequired,
|
||||||
|
|
||||||
accounts: PropTypes.object,
|
|
||||||
allowCopy: PropTypes.bool,
|
allowCopy: PropTypes.bool,
|
||||||
|
allowedValues: PropTypes.array,
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
error: PropTypes.any,
|
error: PropTypes.any,
|
||||||
hint: nodeOrStringProptype(),
|
hint: nodeOrStringProptype(),
|
||||||
@ -97,7 +97,7 @@ export default class TypedInput extends Component {
|
|||||||
const { type } = param;
|
const { type } = param;
|
||||||
|
|
||||||
if (type === ABI_TYPES.ARRAY) {
|
if (type === ABI_TYPES.ARRAY) {
|
||||||
const { accounts, className, label } = this.props;
|
const { allowedValues, className, label } = this.props;
|
||||||
const { subtype, length } = param;
|
const { subtype, length } = param;
|
||||||
const value = this.getValue() || param.default;
|
const value = this.getValue() || param.default;
|
||||||
|
|
||||||
@ -113,8 +113,8 @@ export default class TypedInput extends Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<TypedInput
|
<TypedInput
|
||||||
accounts={ accounts }
|
|
||||||
allowCopy={ allowCopy }
|
allowCopy={ allowCopy }
|
||||||
|
allowedValues={ allowedValues }
|
||||||
className={ className }
|
className={ className }
|
||||||
key={ `${subtype.type}_${index}` }
|
key={ `${subtype.type}_${index}` }
|
||||||
onChange={ onChange }
|
onChange={ onChange }
|
||||||
@ -340,13 +340,13 @@ export default class TypedInput extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderAddress () {
|
renderAddress () {
|
||||||
const { accounts, allowCopy, className, label, error, hint, readOnly } = this.props;
|
const { allowCopy, allowedValues, className, label, error, hint, readOnly } = this.props;
|
||||||
const value = this.getValue();
|
const value = this.getValue();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InputAddressSelect
|
<InputAddressSelect
|
||||||
allowCopy={ allowCopy }
|
allowCopy={ allowCopy }
|
||||||
accounts={ accounts }
|
allowedValues={ allowedValues }
|
||||||
className={ className }
|
className={ className }
|
||||||
error={ error }
|
error={ error }
|
||||||
hint={ hint }
|
hint={ hint }
|
||||||
|
@ -78,13 +78,39 @@ export default class WalletsUtils {
|
|||||||
.delegateCall(api, walletContract.address, 'fetchTransactions', [ walletContract ])
|
.delegateCall(api, walletContract.address, 'fetchTransactions', [ walletContract ])
|
||||||
.then((transactions) => {
|
.then((transactions) => {
|
||||||
return transactions.sort((txA, txB) => {
|
return transactions.sort((txA, txB) => {
|
||||||
const comp = txB.blockNumber.comparedTo(txA.blockNumber);
|
const bnA = txA.blockNumber;
|
||||||
|
const bnB = txB.blockNumber;
|
||||||
|
|
||||||
|
if (!bnA) {
|
||||||
|
console.warn('could not find block number in transaction', txA);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bnB) {
|
||||||
|
console.warn('could not find block number in transaction', txB);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const comp = bnA.comparedTo(bnB);
|
||||||
|
|
||||||
if (comp !== 0) {
|
if (comp !== 0) {
|
||||||
return comp;
|
return comp;
|
||||||
}
|
}
|
||||||
|
|
||||||
return txB.transactionIndex.comparedTo(txA.transactionIndex);
|
const txIdxA = txA.transactionIndex;
|
||||||
|
const txIdxB = txB.transactionIndex;
|
||||||
|
|
||||||
|
if (!txIdxA) {
|
||||||
|
console.warn('could not find transaction index in transaction', txA);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!txIdxB) {
|
||||||
|
console.warn('could not find transaction index in transaction', txB);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return txIdxA.comparedTo(txIdxB);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -212,6 +212,7 @@ export default class ConsensysWalletUtils {
|
|||||||
|
|
||||||
const transaction = {
|
const transaction = {
|
||||||
transactionHash: log.transactionHash,
|
transactionHash: log.transactionHash,
|
||||||
|
transactionIndex: log.transactionIndex,
|
||||||
blockNumber: log.blockNumber
|
blockNumber: log.blockNumber
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -130,27 +130,67 @@ export default class FoundationWalletUtils {
|
|||||||
.ConfirmationNeeded
|
.ConfirmationNeeded
|
||||||
.getAllLogs()
|
.getAllLogs()
|
||||||
.then((logs) => {
|
.then((logs) => {
|
||||||
return logs.map((log) => ({
|
return logs
|
||||||
initiator: log.params.initiator.value,
|
.filter((log) => {
|
||||||
to: log.params.to.value,
|
if (!log.blockNumber) {
|
||||||
data: log.params.data.value,
|
console.warn('got a log without blockNumber', log);
|
||||||
value: log.params.value.value,
|
return false;
|
||||||
operation: bytesToHex(log.params.operation.value),
|
}
|
||||||
transactionIndex: log.transactionIndex,
|
|
||||||
transactionHash: log.transactionHash,
|
if (!log.transactionIndex) {
|
||||||
blockNumber: log.blockNumber,
|
console.warn('got a log without transactionIndex', log);
|
||||||
confirmedBy: []
|
return false;
|
||||||
}));
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.map((log) => ({
|
||||||
|
initiator: log.params.initiator.value,
|
||||||
|
to: log.params.to.value,
|
||||||
|
data: log.params.data.value,
|
||||||
|
value: log.params.value.value,
|
||||||
|
operation: bytesToHex(log.params.operation.value),
|
||||||
|
transactionIndex: log.transactionIndex,
|
||||||
|
transactionHash: log.transactionHash,
|
||||||
|
blockNumber: log.blockNumber,
|
||||||
|
confirmedBy: []
|
||||||
|
}));
|
||||||
})
|
})
|
||||||
.then((logs) => {
|
.then((logs) => {
|
||||||
return logs.sort((logA, logB) => {
|
return logs.sort((logA, logB) => {
|
||||||
const comp = logA.blockNumber.comparedTo(logB.blockNumber);
|
const bnA = logA.blockNumber;
|
||||||
|
const bnB = logA.blockNumber;
|
||||||
|
|
||||||
|
if (!bnA) {
|
||||||
|
console.warn('could not find block number in log', logA);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bnB) {
|
||||||
|
console.warn('could not find block number in log', logB);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const comp = bnA.comparedTo(bnB);
|
||||||
|
|
||||||
if (comp !== 0) {
|
if (comp !== 0) {
|
||||||
return comp;
|
return comp;
|
||||||
}
|
}
|
||||||
|
|
||||||
return logA.transactionIndex.comparedTo(logB.transactionIndex);
|
const txIdxA = logA.transactionIndex;
|
||||||
|
const txIdxB = logB.transactionIndex;
|
||||||
|
|
||||||
|
if (!txIdxA) {
|
||||||
|
console.warn('could not find transaction index in log', logA);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!txIdxB) {
|
||||||
|
console.warn('could not find transaction index in log', logB);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return txIdxA.comparedTo(txIdxB);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((pendingTxs) => {
|
.then((pendingTxs) => {
|
||||||
@ -205,40 +245,48 @@ export default class FoundationWalletUtils {
|
|||||||
] ]
|
] ]
|
||||||
})
|
})
|
||||||
.then((logs) => {
|
.then((logs) => {
|
||||||
const transactions = logs.map((log) => {
|
const transactions = logs
|
||||||
const signature = toHex(log.topics[0]);
|
.map((log) => {
|
||||||
|
const signature = toHex(log.topics[0]);
|
||||||
|
|
||||||
const value = log.params.value.value;
|
const value = log.params.value.value;
|
||||||
const from = signature === WalletSignatures.Deposit
|
const from = signature === WalletSignatures.Deposit
|
||||||
? log.params['_from'].value
|
? log.params['_from'].value
|
||||||
: walletContract.address;
|
: walletContract.address;
|
||||||
|
|
||||||
const to = signature === WalletSignatures.Deposit
|
const to = signature === WalletSignatures.Deposit
|
||||||
? walletContract.address
|
? walletContract.address
|
||||||
: log.params.to.value;
|
: log.params.to.value;
|
||||||
|
|
||||||
const transaction = {
|
const transaction = {
|
||||||
transactionHash: log.transactionHash,
|
transactionHash: log.transactionHash,
|
||||||
blockNumber: log.blockNumber,
|
transactionIndex: log.transactionIndex,
|
||||||
from, to, value
|
blockNumber: log.blockNumber,
|
||||||
};
|
from, to, value
|
||||||
|
};
|
||||||
|
|
||||||
if (log.params.created && log.params.created.value && !/^(0x)?0*$/.test(log.params.created.value)) {
|
if (!transaction.blockNumber) {
|
||||||
transaction.creates = log.params.created.value;
|
console.warn('log without block number', log);
|
||||||
delete transaction.to;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (log.params.operation) {
|
if (log.params.created && log.params.created.value && !/^(0x)?0*$/.test(log.params.created.value)) {
|
||||||
transaction.operation = bytesToHex(log.params.operation.value);
|
transaction.creates = log.params.created.value;
|
||||||
checkPendingOperation(api, log, transaction.operation);
|
delete transaction.to;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (log.params.data) {
|
if (log.params.operation) {
|
||||||
transaction.data = log.params.data.value;
|
transaction.operation = bytesToHex(log.params.operation.value);
|
||||||
}
|
checkPendingOperation(api, log, transaction.operation);
|
||||||
|
}
|
||||||
|
|
||||||
return transaction;
|
if (log.params.data) {
|
||||||
});
|
transaction.data = log.params.data.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return transaction;
|
||||||
|
})
|
||||||
|
.filter((tx) => tx);
|
||||||
|
|
||||||
return transactions;
|
return transactions;
|
||||||
});
|
});
|
||||||
|
@ -35,7 +35,6 @@ class InputQuery extends Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
accountsInfo: PropTypes.object.isRequired,
|
|
||||||
contract: PropTypes.object.isRequired,
|
contract: PropTypes.object.isRequired,
|
||||||
inputs: arrayOrObjectProptype().isRequired,
|
inputs: arrayOrObjectProptype().isRequired,
|
||||||
outputs: arrayOrObjectProptype().isRequired,
|
outputs: arrayOrObjectProptype().isRequired,
|
||||||
@ -122,7 +121,7 @@ class InputQuery extends Component {
|
|||||||
|
|
||||||
renderResults () {
|
renderResults () {
|
||||||
const { results, isLoading } = this.state;
|
const { results, isLoading } = this.state;
|
||||||
const { accountsInfo, outputs } = this.props;
|
const { outputs } = this.props;
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
@ -143,7 +142,6 @@ class InputQuery extends Component {
|
|||||||
.map((out, index) => {
|
.map((out, index) => {
|
||||||
const input = (
|
const input = (
|
||||||
<TypedInput
|
<TypedInput
|
||||||
accounts={ accountsInfo }
|
|
||||||
allowCopy
|
allowCopy
|
||||||
isEth={ false }
|
isEth={ false }
|
||||||
param={ out.type }
|
param={ out.type }
|
||||||
|
@ -29,7 +29,6 @@ export default class Queries extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
accountsInfo: PropTypes.object.isRequired,
|
|
||||||
contract: PropTypes.object,
|
contract: PropTypes.object,
|
||||||
values: PropTypes.object
|
values: PropTypes.object
|
||||||
}
|
}
|
||||||
@ -94,12 +93,11 @@ export default class Queries extends Component {
|
|||||||
|
|
||||||
renderInputQuery (fn) {
|
renderInputQuery (fn) {
|
||||||
const { abi, name, signature } = fn;
|
const { abi, name, signature } = fn;
|
||||||
const { accountsInfo, contract } = this.props;
|
const { contract } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ styles.container } key={ fn.signature }>
|
<div className={ styles.container } key={ fn.signature }>
|
||||||
<InputQuery
|
<InputQuery
|
||||||
accountsInfo={ accountsInfo }
|
|
||||||
className={ styles.method }
|
className={ styles.method }
|
||||||
inputs={ abi.inputs }
|
inputs={ abi.inputs }
|
||||||
outputs={ abi.outputs }
|
outputs={ abi.outputs }
|
||||||
@ -144,13 +142,11 @@ export default class Queries extends Component {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { accountsInfo } = this.props;
|
|
||||||
const { name, type } = output;
|
const { name, type } = output;
|
||||||
const label = `${name ? `${name}: ` : ''}${type}`;
|
const label = `${name ? `${name}: ` : ''}${type}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TypedInput
|
<TypedInput
|
||||||
accounts={ accountsInfo }
|
|
||||||
allowCopy
|
allowCopy
|
||||||
key={ key }
|
key={ key }
|
||||||
isEth={ false }
|
isEth={ false }
|
||||||
|
@ -45,7 +45,6 @@ class Contract extends Component {
|
|||||||
setVisibleAccounts: PropTypes.func.isRequired,
|
setVisibleAccounts: PropTypes.func.isRequired,
|
||||||
|
|
||||||
accounts: PropTypes.object,
|
accounts: PropTypes.object,
|
||||||
accountsInfo: PropTypes.object,
|
|
||||||
contracts: PropTypes.object,
|
contracts: PropTypes.object,
|
||||||
netVersion: PropTypes.string.isRequired,
|
netVersion: PropTypes.string.isRequired,
|
||||||
params: PropTypes.object
|
params: PropTypes.object
|
||||||
@ -128,7 +127,7 @@ class Contract extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { accountsInfo, contracts, netVersion, params } = this.props;
|
const { contracts, netVersion, params } = this.props;
|
||||||
const { allEvents, contract, queryValues, loadingEvents } = this.state;
|
const { allEvents, contract, queryValues, loadingEvents } = this.state;
|
||||||
const account = contracts[params.address];
|
const account = contracts[params.address];
|
||||||
|
|
||||||
@ -150,7 +149,6 @@ class Contract extends Component {
|
|||||||
{ this.renderBlockNumber(account.meta) }
|
{ this.renderBlockNumber(account.meta) }
|
||||||
</Header>
|
</Header>
|
||||||
<Queries
|
<Queries
|
||||||
accountsInfo={ accountsInfo }
|
|
||||||
contract={ contract }
|
contract={ contract }
|
||||||
values={ queryValues }
|
values={ queryValues }
|
||||||
/>
|
/>
|
||||||
@ -530,12 +528,11 @@ class Contract extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
const { accounts, accountsInfo, contracts } = state.personal;
|
const { accounts, contracts } = state.personal;
|
||||||
const { netVersion } = state.nodeStatus;
|
const { netVersion } = state.nodeStatus;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
accounts,
|
accounts,
|
||||||
accountsInfo,
|
|
||||||
contracts,
|
contracts,
|
||||||
netVersion
|
netVersion
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user