Fix contract queries bug (#4534)
* Fix contract queries and multiple Address Selector issues * Linting * Use standard new Error
This commit is contained in:
parent
fefd53d4f4
commit
e8597e2e91
@ -241,13 +241,32 @@ export default class Contract {
|
|||||||
_bindFunction = (func) => {
|
_bindFunction = (func) => {
|
||||||
func.contract = this;
|
func.contract = this;
|
||||||
|
|
||||||
func.call = (options, values = []) => {
|
func.call = (_options = {}, values = []) => {
|
||||||
const callParams = this._encodeOptions(func, this._addOptionsTo(options), values);
|
const rawTokens = !!_options.rawTokens;
|
||||||
|
const options = {
|
||||||
|
..._options
|
||||||
|
};
|
||||||
|
|
||||||
|
delete options.rawTokens;
|
||||||
|
|
||||||
|
let callParams;
|
||||||
|
|
||||||
|
try {
|
||||||
|
callParams = this._encodeOptions(func, this._addOptionsTo(options), values);
|
||||||
|
} catch (error) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
|
||||||
return this._api.eth
|
return this._api.eth
|
||||||
.call(callParams)
|
.call(callParams)
|
||||||
.then((encoded) => func.decodeOutput(encoded))
|
.then((encoded) => func.decodeOutput(encoded))
|
||||||
.then((tokens) => tokens.map((token) => token.value))
|
.then((tokens) => {
|
||||||
|
if (rawTokens) {
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tokens.map((token) => token.value);
|
||||||
|
})
|
||||||
.then((returns) => returns.length === 1 ? returns[0] : returns)
|
.then((returns) => returns.length === 1 ? returns[0] : returns)
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.warn(`${func.name}.call`, values, error);
|
console.warn(`${func.name}.call`, values, error);
|
||||||
@ -257,7 +276,13 @@ export default class Contract {
|
|||||||
|
|
||||||
if (!func.constant) {
|
if (!func.constant) {
|
||||||
func.postTransaction = (options, values = []) => {
|
func.postTransaction = (options, values = []) => {
|
||||||
const _options = this._encodeOptions(func, this._addOptionsTo(options), values);
|
let _options;
|
||||||
|
|
||||||
|
try {
|
||||||
|
_options = this._encodeOptions(func, this._addOptionsTo(options), values);
|
||||||
|
} catch (error) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
|
||||||
return this._api.parity
|
return this._api.parity
|
||||||
.postTransaction(_options)
|
.postTransaction(_options)
|
||||||
|
@ -107,6 +107,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
.categories {
|
.categories {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
@ -206,12 +206,11 @@ class AddressSelect extends Component {
|
|||||||
style={ BOTTOM_BORDER_STYLE }
|
style={ BOTTOM_BORDER_STYLE }
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{ this.renderCurrentInput() }
|
|
||||||
{ this.renderRegistryValues() }
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
{ this.renderCurrentInput() }
|
||||||
|
{ this.renderRegistryValues() }
|
||||||
{ this.renderAccounts() }
|
{ this.renderAccounts() }
|
||||||
</Portal>
|
</Portal>
|
||||||
);
|
);
|
||||||
@ -245,8 +244,8 @@ class AddressSelect extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className={ styles.container }>
|
||||||
{ this.renderAccountCard({ address }) }
|
{ this.renderAccountCard({ address, index: 'currentInput_0' }) }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -266,7 +265,7 @@ class AddressSelect extends Component {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className={ styles.container }>
|
||||||
{ accounts }
|
{ accounts }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -361,7 +360,7 @@ class AddressSelect extends Component {
|
|||||||
|
|
||||||
validateCustomInput = () => {
|
validateCustomInput = () => {
|
||||||
const { allowInput } = this.props;
|
const { allowInput } = this.props;
|
||||||
const { inputValue } = this.store;
|
const { inputValue } = this.state;
|
||||||
const { values } = this.store;
|
const { values } = this.store;
|
||||||
|
|
||||||
// If input is HEX and allowInput === true, send it
|
// If input is HEX and allowInput === true, send it
|
||||||
@ -587,7 +586,13 @@ class AddressSelect extends Component {
|
|||||||
this.handleDOMAction('inputAddress', 'focus');
|
this.handleDOMAction('inputAddress', 'focus');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({ expanded: false });
|
this.store.resetRegistryValues();
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
expanded: false,
|
||||||
|
focusedItem: null,
|
||||||
|
inputValue: ''
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleInputBlur = () => {
|
handleInputBlur = () => {
|
||||||
|
@ -204,6 +204,10 @@ export default class AddressSelectStore {
|
|||||||
this.handleChange();
|
this.handleChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action resetRegistryValues = () => {
|
||||||
|
this.registryValues = [];
|
||||||
|
}
|
||||||
|
|
||||||
@action handleChange = (value = '') => {
|
@action handleChange = (value = '') => {
|
||||||
let index = 0;
|
let index = 0;
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ export default class TypedInput extends Component {
|
|||||||
return (
|
return (
|
||||||
<div className={ styles.inputs }>
|
<div className={ styles.inputs }>
|
||||||
<label>{ label }</label>
|
<label>{ label }</label>
|
||||||
{ fixedLength ? null : this.renderLength() }
|
{ fixedLength || readOnly ? null : this.renderLength() }
|
||||||
{ inputs }
|
{ inputs }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -14,17 +14,19 @@
|
|||||||
// 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 BigNumber from 'bignumber.js';
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import LinearProgress from 'material-ui/LinearProgress';
|
import LinearProgress from 'material-ui/LinearProgress';
|
||||||
import { Card, CardActions, CardTitle, CardText } from 'material-ui/Card';
|
import { Card, CardActions, CardTitle, CardText } from 'material-ui/Card';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { bindActionCreators } from 'redux';
|
||||||
|
|
||||||
|
import { newError } from '~/redux/actions';
|
||||||
import { Button, TypedInput } from '~/ui';
|
import { Button, TypedInput } from '~/ui';
|
||||||
import { arrayOrObjectProptype } from '~/util/proptypes';
|
import { arrayOrObjectProptype } from '~/util/proptypes';
|
||||||
|
|
||||||
import styles from './queries.css';
|
import styles from './queries.css';
|
||||||
|
|
||||||
export default class InputQuery extends Component {
|
class InputQuery extends Component {
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
api: PropTypes.object
|
api: PropTypes.object
|
||||||
};
|
};
|
||||||
@ -35,6 +37,7 @@ export default class InputQuery extends Component {
|
|||||||
inputs: arrayOrObjectProptype().isRequired,
|
inputs: arrayOrObjectProptype().isRequired,
|
||||||
outputs: arrayOrObjectProptype().isRequired,
|
outputs: arrayOrObjectProptype().isRequired,
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
|
newError: PropTypes.func.isRequired,
|
||||||
signature: PropTypes.string.isRequired,
|
signature: PropTypes.string.isRequired,
|
||||||
className: PropTypes.string
|
className: PropTypes.string
|
||||||
};
|
};
|
||||||
@ -65,7 +68,7 @@ export default class InputQuery extends Component {
|
|||||||
const { isValid } = this.state;
|
const { isValid } = this.state;
|
||||||
|
|
||||||
const inputsFields = inputs
|
const inputsFields = inputs
|
||||||
.map(input => this.renderInput(input));
|
.map((input, index) => this.renderInput(input, index));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@ -119,7 +122,7 @@ export default class InputQuery extends Component {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={ index }>
|
<div key={ `${out.name}_${out.type}_${index}` }>
|
||||||
<div className={ styles.queryResultName }>
|
<div className={ styles.queryResultName }>
|
||||||
{ out.name }
|
{ out.name }
|
||||||
</div>
|
</div>
|
||||||
@ -129,7 +132,7 @@ export default class InputQuery extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
renderInput (input) {
|
renderInput (input, index) {
|
||||||
const { values } = this.state;
|
const { values } = this.state;
|
||||||
const { name, type } = input;
|
const { name, type } = input;
|
||||||
const label = `${name ? `${name}: ` : ''}${type}`;
|
const label = `${name ? `${name}: ` : ''}${type}`;
|
||||||
@ -140,41 +143,42 @@ export default class InputQuery extends Component {
|
|||||||
this.setState({
|
this.setState({
|
||||||
values: {
|
values: {
|
||||||
...values,
|
...values,
|
||||||
[ name ]: value
|
[ index ]: value
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={ name }>
|
<div key={ `${name}_${type}_${index}` }>
|
||||||
<TypedInput
|
<TypedInput
|
||||||
hint={ type }
|
hint={ type }
|
||||||
label={ label }
|
label={ label }
|
||||||
isEth={ false }
|
isEth={ false }
|
||||||
onChange={ onChange }
|
onChange={ onChange }
|
||||||
param={ type }
|
param={ type }
|
||||||
value={ values[name] }
|
value={ values[index] }
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderValue (value) {
|
renderValue (token) {
|
||||||
|
const { api } = this.context;
|
||||||
|
const { type, value } = token;
|
||||||
|
|
||||||
if (value === null || value === undefined) {
|
if (value === null || value === undefined) {
|
||||||
return 'no data';
|
return 'no data';
|
||||||
}
|
}
|
||||||
|
|
||||||
const { api } = this.context;
|
if (type === 'array' || type === 'fixedArray') {
|
||||||
|
return value.map((tok) => this.renderValue(tok));
|
||||||
if (api.util.isInstanceOf(value, BigNumber)) {
|
|
||||||
return value.toFormat(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (api.util.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
return api.util.bytesToHex(value);
|
return api.util.bytesToHex(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return value.toString();
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
onClick = () => {
|
onClick = () => {
|
||||||
@ -186,11 +190,11 @@ export default class InputQuery extends Component {
|
|||||||
results: []
|
results: []
|
||||||
});
|
});
|
||||||
|
|
||||||
const inputValues = inputs.map(input => values[input.name]);
|
const inputValues = inputs.map((input, index) => values[index] || '');
|
||||||
|
|
||||||
contract
|
contract
|
||||||
.instance[signature]
|
.instance[signature]
|
||||||
.call({}, inputValues)
|
.call({ rawTokens: true }, inputValues)
|
||||||
.then(results => {
|
.then(results => {
|
||||||
if (outputs.length === 1) {
|
if (outputs.length === 1) {
|
||||||
results = [ results ];
|
results = [ results ];
|
||||||
@ -201,8 +205,24 @@ export default class InputQuery extends Component {
|
|||||||
results
|
results
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(e => {
|
.catch((error) => {
|
||||||
console.error(`sending ${name} with params`, inputValues, e);
|
console.error(`sending ${name} with params`, inputValues, error.message);
|
||||||
|
|
||||||
|
this.props.newError(error);
|
||||||
|
this.setState({
|
||||||
|
isLoading: false
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mapDispatchToProps (dispatch) {
|
||||||
|
return bindActionCreators({
|
||||||
|
newError
|
||||||
|
}, dispatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
null,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(InputQuery);
|
||||||
|
@ -61,12 +61,25 @@ export default class Queries extends Component {
|
|||||||
return (
|
return (
|
||||||
<Container title='queries'>
|
<Container title='queries'>
|
||||||
<div className={ styles.methods }>
|
<div className={ styles.methods }>
|
||||||
<div className={ styles.vMethods }>
|
{
|
||||||
{ noInputQueries }
|
noInputQueries.length > 0
|
||||||
</div>
|
? (
|
||||||
<div className={ styles.hMethods }>
|
<div className={ styles.vMethods }>
|
||||||
{ withInputQueries }
|
{ noInputQueries }
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
withInputQueries.length > 0
|
||||||
|
? (
|
||||||
|
<div className={ styles.hMethods }>
|
||||||
|
{ withInputQueries }
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
: null
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user