add gas price estimator is functions as well as a button to auto-set

This commit is contained in:
Jonathan Rainville 2018-10-25 11:59:25 -04:00
parent 92d433ff9a
commit 8886f6b0f2
6 changed files with 67 additions and 23 deletions

View File

@ -7,3 +7,15 @@
bottom: 15px;
right: 15px;
}
.contract-function-container .gas-price-form #gasPrice {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.contract-function-container .gas-price-form button {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
border: 0;
box-shadow: none !important;
}

View File

@ -17,6 +17,7 @@ import {
ListGroup,
ListGroupItem
} from "reactstrap";
import GasStationContainer from "../containers/GasStationContainer";
import {formatContractForDisplay} from '../utils/presentation';
import FontAwesome from 'react-fontawesome';
@ -25,7 +26,7 @@ import "./ContractOverview.css";
class ContractFunction extends Component {
constructor(props) {
super(props);
this.state = {inputs: {}, optionsCollapse: false, functionCollapse: false};
this.state = {inputs: {}, optionsCollapse: false, functionCollapse: false, gasPriceCollapse: false};
}
static isPureCall(method) {
@ -52,11 +53,18 @@ class ContractFunction extends Component {
}
handleChange(e, name) {
let newInputs = this.state.inputs;
const newInputs = this.state.inputs;
newInputs[name] = e.target.value;
this.setState({inputs: newInputs});
}
autoSetGasPrice(e) {
e.preventDefault();
const newInputs = this.state.inputs;
newInputs.gasPrice = this.gasStation.getCurrentGas();
this.setState({inputs: newInputs});
}
handleCall(e) {
e.preventDefault();
this.props.postContractFunction(this.props.contractProfile.name, this.props.method.name, this.inputsAsArray(), this.state.inputs.gasPrice * 1000000000);
@ -72,6 +80,12 @@ class ContractFunction extends Component {
});
}
toggleGasPrice() {
this.setState({
gasPriceCollapse: !this.state.gasPriceCollapse
});
}
toggleFunction() {
this.setState({
functionCollapse: !this.state.functionCollapse
@ -84,7 +98,7 @@ class ContractFunction extends Component {
<CardHeader>
<CardTitle className="collapsable" onClick={() => this.toggleFunction()}>
{ContractFunction.isPureCall(this.props.method) &&
<button className="btn btn-warning btn-sm float-right">call</button>
<button className="btn btn-warning btn-sm float-right" onClick={(e) => this.handleCall(e)}>call</button>
}
{ContractFunction.isEvent(this.props.method) &&
<button className="btn btn-info btn-sm float-right">event</button>
@ -107,24 +121,38 @@ class ContractFunction extends Component {
<Col xs={12} className="mt-3">
<Row>
<strong className="collapsable" onClick={() => this.toggleOptions()}>
<FontAwesome name={this.state.optionsCollapse ? 'caret-down' : 'caret-right'} className="mr-2"/>Advanced
Options
<FontAwesome name={this.state.optionsCollapse ? 'caret-down' : 'caret-right'} className="mr-2"/>
Advanced Options
</strong>
</Row>
<Row>
<Collapse isOpen={this.state.optionsCollapse} className="pl-3">
<Form method="post" inline>
<Form method="post" inline className="gas-price-form ">
<FormGroup key="gasPrice">
<Label for="gasPrice" className="mr-2">Gas Price (in GWei)(optional)</Label>
<Input name="gasPrice" id="gasPrice" placeholder="uint256"
value={this.state.inputs.gasPrice || ''}
onChange={(e) => this.handleChange(e, 'gasPrice')}/>
<Button onClick={(e) => this.autoSetGasPrice(e)}>
Auto-set
</Button>
</FormGroup>
</Form>
<p className="collapsable mb-2" onClick={() => this.toggleGasPrice()}>
<FontAwesome name={this.state.gasPriceCollapse ? 'caret-down' : 'caret-right'} className="mr-2"/>
Gas price estimator
</p>
<Collapse isOpen={this.state.gasPriceCollapse}>
<GasStationContainer ref={instance => {
if (instance) this.gasStation = instance.getWrappedInstance();
}}/>
</Collapse>
</Collapse>
</Row>
</Col>
}
<Button className="contract-function-button" color="primary" disabled={this.callDisabled()} onClick={(e) => this.handleCall(e)}>
<Button className="contract-function-button" color="primary" disabled={this.callDisabled()}
onClick={(e) => this.handleCall(e)}>
{this.buttonTitle()}
</Button>
</CardBody>

View File

@ -1,4 +1,4 @@
.copy-to-clipboard {
#root .copy-to-clipboard {
position: absolute;
right: 0;
top: 0;

View File

@ -49,6 +49,10 @@ class GasStation extends Component {
return formattedStats;
}
getCurrentGas() {
return this.getGasOracleFormatted()[this.state.gasOracleSliderIndex].gasPrice / this.PRICE_UNIT_DIVIDER;
}
gasSliderChange(e, name) {
this.setState({
[name]: e.target.value
@ -91,7 +95,7 @@ class GasStation extends Component {
}
return <Row>
<Col>
<Card>
<Card className="mb-0">
<CardHeader>
<CardTitle>
Gas Price Estimator

View File

@ -5,7 +5,6 @@ import PropTypes from 'prop-types';
import {contractProfile as contractProfileAction, contractFunction as contractFunctionAction} from '../actions';
import ContractOverview from '../components/ContractOverview';
import DataWrapper from "../components/DataWrapper";
import GasStationContainer from "../containers/GasStationContainer";
import {getContractProfile, getContractFunctions} from "../reducers/selectors";
class ContractOverviewContainer extends Component {
@ -18,14 +17,10 @@ class ContractOverviewContainer extends Component {
<DataWrapper shouldRender={this.props.contractProfile !== undefined}
{...this.props}
render={({contractProfile, contractFunctions, postContractFunction}) => (
<React.Fragment>
<ContractOverview contractProfile={contractProfile}
contractFunctions={contractFunctions}
contract={this.props.contract}
postContractFunction={postContractFunction}/>
<GasStationContainer/>
</React.Fragment>
<ContractOverview contractProfile={contractProfile}
contractFunctions={contractFunctions}
contract={this.props.contract}
postContractFunction={postContractFunction}/>
)}/>
);
}

View File

@ -1,7 +1,6 @@
import PropTypes from "prop-types";
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {withRouter} from "react-router-dom";
import GasStation from '../components/GasStation';
import {stopGasOracle, listenToGasOracle, gasOracle as ethGasAction, blocks as blocksAction} from "../actions";
import DataWrapper from "../components/DataWrapper";
@ -18,10 +17,14 @@ class GasStationContainer extends Component {
this.props.stopGasOracle();
}
getCurrentGas() {
return this.gasStation.getCurrentGas();
}
render() {
return <DataWrapper shouldRender={Boolean(this.props.gasOracleStats && Object.keys(this.props.gasOracleStats).length && this.props.lastBlock)}
{...this.props} render={({lastBlock, gasOracleStats}) => (
<GasStation gasOracleStats={gasOracleStats} lastBlock={lastBlock}/>
<GasStation gasOracleStats={gasOracleStats} lastBlock={lastBlock} ref={instance => { this.gasStation = instance; }}/>
)}/>;
}
@ -43,12 +46,14 @@ function mapStateToProps(state, _props) {
};
}
export default withRouter(connect(
export default connect(
mapStateToProps,
{
fetchEthGas: ethGasAction.request,
fetchBlocks: blocksAction.request,
listenToGasOracle,
stopGasOracle
}
)(GasStationContainer));
},
null,
{ withRef: true }
)(GasStationContainer);