add gas station component

This commit is contained in:
Jonathan Rainville 2018-08-28 11:16:24 -04:00 committed by Pascal Precht
parent 7080be9fb1
commit 77258f8636
No known key found for this signature in database
GPG Key ID: 0EE28D8D6FD85D7D
5 changed files with 178 additions and 18 deletions

View File

@ -2,7 +2,6 @@ import axios from "axios";
import constants from '../constants';
function get(path, params, endpoint) {
console.log('GET ', (endpoint || constants.httpEndpoint) + path);
return axios.get((endpoint || constants.httpEndpoint) + path, params)
.then((response) => {
return {response, error: null};

View File

@ -12,11 +12,11 @@ import {
class ContractFunction extends Component {
constructor(props) {
super(props);
this.state = { inputs: {} };
this.state = {inputs: {}};
}
buttonTitle() {
const { method } =this.props;
const {method} = this.props;
if (method.name === 'constructor') {
return 'Deploy';
}
@ -24,7 +24,7 @@ class ContractFunction extends Component {
return (method.mutability === 'view' || method.mutability === 'pure') ? 'Call' : 'Send';
}
inputsAsArray(){
inputsAsArray() {
return this.props.method.inputs
.map(input => this.state.inputs[input.name])
.filter(value => value);
@ -33,7 +33,7 @@ class ContractFunction extends Component {
handleChange(e, name) {
let newInputs = this.state.inputs;
newInputs[name] = e.target.value;
this.setState({ inputs: newInputs});
this.setState({inputs: newInputs});
}
handleCall(e) {
@ -63,7 +63,7 @@ class ContractFunction extends Component {
{this.buttonTitle()}
</Button>
</Card.Body>
<Card.Footer>
{this.props.contractFunctions && this.props.contractFunctions.length > 0 && <Card.Footer>
<List>
{this.props.contractFunctions.map(contractFunction => (
<List.Item key={contractFunction.result}>
@ -72,7 +72,7 @@ class ContractFunction extends Component {
</List.Item>
))}
</List>
</Card.Footer>
</Card.Footer>}
</Card>
</Grid.Col>
</Grid.Row>
@ -106,7 +106,7 @@ const ContractFunctions = (props) => {
method={method}
contractFunctions={filterContractFunctions(props.contractFunctions, contractProfile.name, method.name)}
contractProfile={contractProfile}
postContractFunction={props.postContractFunction} />)}
postContractFunction={props.postContractFunction}/>)}
</Page.Content>
);
};

View File

@ -0,0 +1,142 @@
import PropTypes from "prop-types";
import React, {Component} from 'react';
import {Card, Form, Grid, StampCard} from 'tabler-react';
const test = {
"fast": 50.0,
"speed": 0.998437456605574,
"fastest": 400.0,
"avgWait": 1.9,
"fastWait": 0.7,
"blockNum": 6228803,
"safeLowWait": 1.9,
"block_time": 14.326530612244898,
"fastestWait": 0.5,
"safeLow": 24.0,
"average": 24.0
};
const COLORS = {
good: 'green',
medium: 'yellow',
bad: 'red'
};
class GasStation extends Component {
constructor(props) {
super(props);
if (!props.gasStats) {
return console.error('gasStats is a needed Prop for GasStation');
}
this.state = {gasSliderIndex: 0};
this.formattedGasStats = GasStation.formatGasStats(props.gasStats);
}
static formatGasStats(gasStats) {
const {
fast, speed, fastest, avgWait, fastWait, blockNum, safeLowWait,
block_time, fastestWait, safeLow, average
} = gasStats;
return {
average: {price: average, wait: avgWait},
blockTime: block_time,
blockNum,
speed,
gasSteps: [
{price: safeLow, wait: safeLowWait},
{price: fast, wait: fastWait},
{price: fastest, wait: fastestWait}
]
};
}
gasSliderChange(e) {
this.setState({
gasSliderIndex: e.target.value
});
}
static getColorForWait(wait) {
if (wait <= 1) {
return COLORS.good;
}
if (wait <= 3) {
return COLORS.medium;
}
return COLORS.bad;
}
static getColorForPrice(gasPrice) {
if (gasPrice <= 20) {
return COLORS.good;
}
if (gasPrice <= 40) {
return COLORS.medium;
}
return COLORS.bad;
}
render() {
const currentGasStep = this.formattedGasStats.gasSteps[this.state.gasSliderIndex];
return <Grid.Row>
<Grid.Col>
<Card>
<Card.Header>
<Card.Title>Gas Price Estimator</Card.Title>
</Card.Header>
<Card.Body>
<Grid.Row cards={true}>
<Grid.Col lg={6} md={6} sm={12}>
<StampCard icon="sliders" color={GasStation.getColorForPrice(currentGasStep.price)}>
{currentGasStep.price / 10} GWei
</StampCard>
</Grid.Col>
<Grid.Col lg={6} md={6} sm={12}>
<StampCard icon="clock" color={GasStation.getColorForWait(currentGasStep.wait)}>
{currentGasStep.wait} minutes
</StampCard>
</Grid.Col>
</Grid.Row>
<Form.Group>
<Form.Ratio
defaultValue={0}
max={this.formattedGasStats.gasSteps.length - 1}
min={0}
step={1}
value={this.state.gasSliderIndex}
onChange={(e) => this.gasSliderChange(e)}
/>
</Form.Group>
<Grid.Row cards={true}>
<Grid.Col lg={4} md={6} sm={12}>
<StampCard icon="sliders" color="grey">
Average Price: {this.formattedGasStats.average.price / 10} Gwei
</StampCard>
</Grid.Col>
<Grid.Col lg={4} md={6} sm={12}>
<StampCard icon="clock" color="grey">
Average Wait: {this.formattedGasStats.average.wait} min
</StampCard>
</Grid.Col>
<Grid.Col lg={4} md={6} sm={12}>
<StampCard icon="square" color="grey">
Last Block: {this.formattedGasStats.blockNum}
</StampCard>
</Grid.Col>
</Grid.Row>
</Card.Body>
</Card>
</Grid.Col>
</Grid.Row>;
}
}
GasStation.propTypes = {
gasStats: PropTypes.object.isRequired
};
export default GasStation;

View File

@ -3,10 +3,15 @@ import {connect} from 'react-redux';
import PropTypes from 'prop-types';
import {withRouter} from 'react-router-dom';
import {contractProfile as contractProfileAction, contractDeploy as contractDeployAction, ethGas as ethGasAction} from '../actions';
import {
contractProfile as contractProfileAction,
contractDeploy as contractDeployAction,
ethGas as ethGasAction
} from '../actions';
import ContractFunctions from '../components/ContractFunctions';
import DataWrapper from "../components/DataWrapper";
import {getContractProfile, getContractDeploys} from "../reducers/selectors";
import GasStation from "../components/GasStation";
import {getContractProfile, getContractDeploys, getGasStats} from "../reducers/selectors";
class ContractDeploymentContainer extends Component {
componentDidMount() {
@ -16,14 +21,23 @@ class ContractDeploymentContainer extends Component {
render() {
return (
<DataWrapper shouldRender={this.props.contractProfile !== undefined }
{...this.props}
render={({contractProfile, contractDeploys, postContractDeploy}) => (
<ContractFunctions contractProfile={contractProfile}
contractFunctions={contractDeploys}
onlyConstructor
postContractFunction={postContractDeploy}/>
)} />
<React.Fragment>
<DataWrapper shouldRender={this.props.contractProfile !== undefined}
{...this.props}
render={({contractProfile, contractDeploys, postContractDeploy}) => (
<ContractFunctions contractProfile={contractProfile}
contractFunctions={contractDeploys}
onlyConstructor
postContractFunction={postContractDeploy}/>
)}/>
<DataWrapper shouldRender={this.props.gasStats !== undefined}
{...this.props}
render={({gasStats}) => (
<GasStation gasStats={gasStats}/>
)}/>
</React.Fragment>
);
}
}
@ -32,6 +46,7 @@ function mapStateToProps(state, props) {
return {
contractProfile: getContractProfile(state, props.match.params.contractName),
contractDeploys: getContractDeploys(state, props.match.params.contractName),
gasStats: getGasStats(state),
error: state.errorMessage,
loading: state.loading
};

View File

@ -84,6 +84,10 @@ export function getVersions(state) {
return state.entities.versions;
}
export function getGasStats(state) {
return state.entities.gasStats[state.entities.gasStats.length - 1];
}
export function isWeb3Enabled(state) {
return Boolean(state.entities.versions.find((version) => version.name === 'web3'));
}