Fix MethodDecoding for Arrays (#4977)
* Fix TypedInputs * Remove unused code in inputQueries * Use TypedInputs in Contract Events * Linting * Don't re-render events every second...
This commit is contained in:
parent
c7e6992239
commit
030d01102c
@ -28,6 +28,6 @@
|
|||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container {
|
.container > * {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
color: rgba(255, 255, 255, 0.498039);
|
color: rgba(255, 255, 255, 0.498039);
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
top: 11px;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import AddIcon from 'material-ui/svg-icons/content/add';
|
|||||||
import RemoveIcon from 'material-ui/svg-icons/content/remove';
|
import RemoveIcon from 'material-ui/svg-icons/content/remove';
|
||||||
|
|
||||||
import { fromWei, toWei } from '~/api/util/wei';
|
import { fromWei, toWei } from '~/api/util/wei';
|
||||||
|
import { bytesToHex } from '~/api/util/format';
|
||||||
import Input from '~/ui/Form/Input';
|
import Input from '~/ui/Form/Input';
|
||||||
import InputAddressSelect from '~/ui/Form/InputAddressSelect';
|
import InputAddressSelect from '~/ui/Form/InputAddressSelect';
|
||||||
import Select from '~/ui/Form/Select';
|
import Select from '~/ui/Form/Select';
|
||||||
@ -68,7 +69,8 @@ export default class TypedInput extends Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
componentWillMount () {
|
componentWillMount () {
|
||||||
const { isEth, value } = this.props;
|
const { isEth } = this.props;
|
||||||
|
const value = this.getValue();
|
||||||
|
|
||||||
if (typeof isEth === 'boolean' && value) {
|
if (typeof isEth === 'boolean' && value) {
|
||||||
// Remove formatting commas
|
// Remove formatting commas
|
||||||
@ -95,14 +97,15 @@ 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, value = param.default } = this.props;
|
const { accounts, className, label } = this.props;
|
||||||
const { subtype, length } = param;
|
const { subtype, length } = param;
|
||||||
|
const value = this.getValue() || param.default;
|
||||||
|
|
||||||
const fixedLength = !!length;
|
const fixedLength = !!length;
|
||||||
|
|
||||||
const inputs = range(length || value.length).map((_, index) => {
|
const inputs = range(length || value.length).map((_, index) => {
|
||||||
const onChange = (inputValue) => {
|
const onChange = (inputValue) => {
|
||||||
const newValues = [].concat(this.props.value);
|
const newValues = [].concat(value);
|
||||||
|
|
||||||
newValues[index] = inputValue;
|
newValues[index] = inputValue;
|
||||||
this.props.onChange(newValues);
|
this.props.onChange(newValues);
|
||||||
@ -191,7 +194,14 @@ export default class TypedInput extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type === ABI_TYPES.BYTES) {
|
if (type === ABI_TYPES.BYTES) {
|
||||||
return this.renderDefault();
|
let value = this.getValue();
|
||||||
|
|
||||||
|
// Convert to hex if it's an array
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
value = bytesToHex(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.renderDefault(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the `isEth` prop is present (true or false)
|
// If the `isEth` prop is present (true or false)
|
||||||
@ -260,7 +270,7 @@ export default class TypedInput extends Component {
|
|||||||
: bnValue.toFixed(); // we need a string representation, could be >15 digits
|
: bnValue.toFixed(); // we need a string representation, could be >15 digits
|
||||||
}
|
}
|
||||||
|
|
||||||
renderInteger (value = this.props.value, onChange = this.onChange) {
|
renderInteger (value = this.getValue(), onChange = this.onChange) {
|
||||||
const { allowCopy, className, label, error, hint, min, max, readOnly } = this.props;
|
const { allowCopy, className, label, error, hint, min, max, readOnly } = this.props;
|
||||||
const param = this.getParam();
|
const param = this.getParam();
|
||||||
|
|
||||||
@ -268,7 +278,7 @@ export default class TypedInput extends Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Input
|
<Input
|
||||||
allowCopy={ allowCopy }
|
allowCopy={ allowCopy ? value : undefined }
|
||||||
className={ className }
|
className={ className }
|
||||||
label={ label }
|
label={ label }
|
||||||
hint={ hint }
|
hint={ hint }
|
||||||
@ -291,7 +301,7 @@ export default class TypedInput extends Component {
|
|||||||
*
|
*
|
||||||
* @see https://github.com/facebook/react/issues/1549
|
* @see https://github.com/facebook/react/issues/1549
|
||||||
*/
|
*/
|
||||||
renderFloat (value = this.props.value, onChange = this.onChange) {
|
renderFloat (value = this.getValue(), onChange = this.onChange) {
|
||||||
const { allowCopy, className, label, error, hint, min, max, readOnly } = this.props;
|
const { allowCopy, className, label, error, hint, min, max, readOnly } = this.props;
|
||||||
const param = this.getParam();
|
const param = this.getParam();
|
||||||
|
|
||||||
@ -299,7 +309,7 @@ export default class TypedInput extends Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Input
|
<Input
|
||||||
allowCopy={ allowCopy }
|
allowCopy={ allowCopy ? value : undefined }
|
||||||
className={ className }
|
className={ className }
|
||||||
label={ label }
|
label={ label }
|
||||||
hint={ hint }
|
hint={ hint }
|
||||||
@ -314,8 +324,8 @@ export default class TypedInput extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderDefault () {
|
renderDefault (value = this.getValue()) {
|
||||||
const { allowCopy, className, label, value, error, hint, readOnly } = this.props;
|
const { allowCopy, className, label, error, hint, readOnly } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Input
|
<Input
|
||||||
@ -332,7 +342,8 @@ export default class TypedInput extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderAddress () {
|
renderAddress () {
|
||||||
const { accounts, allowCopy, className, label, value, error, hint, readOnly } = this.props;
|
const { accounts, allowCopy, className, label, error, hint, readOnly } = this.props;
|
||||||
|
const value = this.getValue();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InputAddressSelect
|
<InputAddressSelect
|
||||||
@ -350,7 +361,8 @@ export default class TypedInput extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderBoolean () {
|
renderBoolean () {
|
||||||
const { allowCopy, className, label, value, error, hint, readOnly } = this.props;
|
const { allowCopy, className, label, error, hint, readOnly } = this.props;
|
||||||
|
const value = this.getValue();
|
||||||
|
|
||||||
if (readOnly) {
|
if (readOnly) {
|
||||||
return this.renderDefault();
|
return this.renderDefault();
|
||||||
@ -441,7 +453,7 @@ export default class TypedInput extends Component {
|
|||||||
onChange(newValues);
|
onChange(newValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
getParam = () => {
|
getParam () {
|
||||||
const { param } = this.props;
|
const { param } = this.props;
|
||||||
|
|
||||||
if (typeof param === 'string') {
|
if (typeof param === 'string') {
|
||||||
@ -450,4 +462,15 @@ export default class TypedInput extends Component {
|
|||||||
|
|
||||||
return param;
|
return param;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the value comes from `decodeMethodInput`,
|
||||||
|
* it can be an object of the shape:
|
||||||
|
* { value: Object, type: String }
|
||||||
|
*/
|
||||||
|
getValue (value = this.props.value) {
|
||||||
|
return value && value.value
|
||||||
|
? value.value
|
||||||
|
: value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -560,7 +560,7 @@ class MethodDecoding extends Component {
|
|||||||
key={ index }
|
key={ index }
|
||||||
param={ input.type }
|
param={ input.type }
|
||||||
readOnly
|
readOnly
|
||||||
value={ this.renderValue(input.value) }
|
value={ input.value }
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -568,16 +568,6 @@ class MethodDecoding extends Component {
|
|||||||
return inputs;
|
return inputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderValue (value) {
|
|
||||||
const { api } = this.context;
|
|
||||||
|
|
||||||
if (api.util.isArray(value)) {
|
|
||||||
return api.util.bytesToHex(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return value.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
renderTokenValue (value) {
|
renderTokenValue (value) {
|
||||||
const { token } = this.props;
|
const { token } = this.props;
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ export function parseAbiType (type) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type === 'bytes') {
|
if (type === 'bytes' || type === 'fixedBytes') {
|
||||||
return {
|
return {
|
||||||
type: BYTES_TYPE,
|
type: BYTES_TYPE,
|
||||||
default: '0x'
|
default: '0x'
|
||||||
|
@ -19,7 +19,7 @@ import moment from 'moment';
|
|||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { IdentityIcon, IdentityName, Input, InputAddress } from '~/ui';
|
import { IdentityIcon, IdentityName, TypedInput } from '~/ui';
|
||||||
import ShortenedHash from '~/ui/ShortenedHash';
|
import ShortenedHash from '~/ui/ShortenedHash';
|
||||||
import { txLink } from '~/3rdparty/etherscan/links';
|
import { txLink } from '~/3rdparty/etherscan/links';
|
||||||
|
|
||||||
@ -112,42 +112,17 @@ export default class Event extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderParam (name, param) {
|
renderParam (name, param) {
|
||||||
const { api } = this.context;
|
|
||||||
|
|
||||||
switch (param.type) {
|
|
||||||
case 'address':
|
|
||||||
return (
|
return (
|
||||||
<InputAddress
|
<TypedInput
|
||||||
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
|
|
||||||
readOnly
|
|
||||||
allowCopy
|
allowCopy
|
||||||
className={ styles.input }
|
className={ styles.input }
|
||||||
value={ value }
|
|
||||||
label={ name }
|
label={ name }
|
||||||
|
param={ param.type }
|
||||||
|
readOnly
|
||||||
|
value={ param.value }
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
formatBlockTimestamp (block) {
|
formatBlockTimestamp (block) {
|
||||||
if (!block) {
|
if (!block) {
|
||||||
|
@ -46,6 +46,12 @@ export default class Events extends Component {
|
|||||||
events: []
|
events: []
|
||||||
};
|
};
|
||||||
|
|
||||||
|
shouldComponentUpdate (nextProps) {
|
||||||
|
return (nextProps.events !== this.props.events) ||
|
||||||
|
(nextProps.netVersion !== this.props.netVersion) ||
|
||||||
|
(nextProps.isLoading !== this.props.isLoading);
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { events, isLoading, netVersion } = this.props;
|
const { events, isLoading, netVersion } = this.props;
|
||||||
|
|
||||||
|
@ -138,10 +138,8 @@ class InputQuery extends Component {
|
|||||||
.map((out, index) => ({
|
.map((out, index) => ({
|
||||||
name: out.name,
|
name: out.name,
|
||||||
type: out.type,
|
type: out.type,
|
||||||
value: results[index],
|
value: results[index]
|
||||||
display: this.renderValue(results[index])
|
|
||||||
}))
|
}))
|
||||||
.sort((outA, outB) => outA.display.length - outB.display.length)
|
|
||||||
.map((out, index) => {
|
.map((out, index) => {
|
||||||
const input = (
|
const input = (
|
||||||
<TypedInput
|
<TypedInput
|
||||||
@ -150,7 +148,7 @@ class InputQuery extends Component {
|
|||||||
isEth={ false }
|
isEth={ false }
|
||||||
param={ out.type }
|
param={ out.type }
|
||||||
readOnly
|
readOnly
|
||||||
value={ out.display }
|
value={ out.value }
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -195,25 +193,6 @@ class InputQuery extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderValue (token) {
|
|
||||||
const { api } = this.context;
|
|
||||||
const { type, value } = token;
|
|
||||||
|
|
||||||
if (value === null || value === undefined) {
|
|
||||||
return 'no data';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'array' || type === 'fixedArray') {
|
|
||||||
return value.map((tok) => this.renderValue(tok));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Array.isArray(value)) {
|
|
||||||
return api.util.bytesToHex(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
onClick = () => {
|
onClick = () => {
|
||||||
const { inputs, values } = this.state;
|
const { inputs, values } = this.state;
|
||||||
const { contract, name, outputs, signature } = this.props;
|
const { contract, name, outputs, signature } = this.props;
|
||||||
|
@ -139,15 +139,14 @@ export default class Queries extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderValue (tokenValue, output, key) {
|
renderValue (value, output, key) {
|
||||||
if (typeof tokenValue === 'undefined') {
|
if (typeof value === 'undefined') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { accountsInfo } = this.props;
|
const { accountsInfo } = this.props;
|
||||||
const { name, type } = output;
|
const { name, type } = output;
|
||||||
const label = `${name ? `${name}: ` : ''}${type}`;
|
const label = `${name ? `${name}: ` : ''}${type}`;
|
||||||
const value = this.getTokenValue(tokenValue);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TypedInput
|
<TypedInput
|
||||||
@ -163,25 +162,6 @@ export default class Queries extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTokenValue (token) {
|
|
||||||
const { api } = this.context;
|
|
||||||
const { type, value } = token;
|
|
||||||
|
|
||||||
if (value === null || value === undefined) {
|
|
||||||
return 'no data';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'array' || type === 'fixedArray') {
|
|
||||||
return value.map((tok) => this.getTokenValue(tok));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Array.isArray(value)) {
|
|
||||||
return api.util.bytesToHex(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
_sortEntries (a, b) {
|
_sortEntries (a, b) {
|
||||||
return a.name.localeCompare(b.name);
|
return a.name.localeCompare(b.name);
|
||||||
}
|
}
|
||||||
|
@ -578,6 +578,10 @@ class WriteContract extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderContract (contract) {
|
renderContract (contract) {
|
||||||
|
if (!contract) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const { bytecode } = contract;
|
const { bytecode } = contract;
|
||||||
const abi = contract.interface;
|
const abi = contract.interface;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user