mirror of
https://github.com/embarklabs/embark.git
synced 2025-02-17 08:07:51 +00:00
add gas station component
This commit is contained in:
parent
7080be9fb1
commit
77258f8636
@ -2,7 +2,6 @@ import axios from "axios";
|
|||||||
import constants from '../constants';
|
import constants from '../constants';
|
||||||
|
|
||||||
function get(path, params, endpoint) {
|
function get(path, params, endpoint) {
|
||||||
console.log('GET ', (endpoint || constants.httpEndpoint) + path);
|
|
||||||
return axios.get((endpoint || constants.httpEndpoint) + path, params)
|
return axios.get((endpoint || constants.httpEndpoint) + path, params)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
return {response, error: null};
|
return {response, error: null};
|
||||||
|
@ -12,11 +12,11 @@ import {
|
|||||||
class ContractFunction extends Component {
|
class ContractFunction extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = { inputs: {} };
|
this.state = {inputs: {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
buttonTitle() {
|
buttonTitle() {
|
||||||
const { method } =this.props;
|
const {method} = this.props;
|
||||||
if (method.name === 'constructor') {
|
if (method.name === 'constructor') {
|
||||||
return 'Deploy';
|
return 'Deploy';
|
||||||
}
|
}
|
||||||
@ -24,7 +24,7 @@ class ContractFunction extends Component {
|
|||||||
return (method.mutability === 'view' || method.mutability === 'pure') ? 'Call' : 'Send';
|
return (method.mutability === 'view' || method.mutability === 'pure') ? 'Call' : 'Send';
|
||||||
}
|
}
|
||||||
|
|
||||||
inputsAsArray(){
|
inputsAsArray() {
|
||||||
return this.props.method.inputs
|
return this.props.method.inputs
|
||||||
.map(input => this.state.inputs[input.name])
|
.map(input => this.state.inputs[input.name])
|
||||||
.filter(value => value);
|
.filter(value => value);
|
||||||
@ -33,7 +33,7 @@ class ContractFunction extends Component {
|
|||||||
handleChange(e, name) {
|
handleChange(e, name) {
|
||||||
let newInputs = this.state.inputs;
|
let newInputs = this.state.inputs;
|
||||||
newInputs[name] = e.target.value;
|
newInputs[name] = e.target.value;
|
||||||
this.setState({ inputs: newInputs});
|
this.setState({inputs: newInputs});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCall(e) {
|
handleCall(e) {
|
||||||
@ -63,7 +63,7 @@ class ContractFunction extends Component {
|
|||||||
{this.buttonTitle()}
|
{this.buttonTitle()}
|
||||||
</Button>
|
</Button>
|
||||||
</Card.Body>
|
</Card.Body>
|
||||||
<Card.Footer>
|
{this.props.contractFunctions && this.props.contractFunctions.length > 0 && <Card.Footer>
|
||||||
<List>
|
<List>
|
||||||
{this.props.contractFunctions.map(contractFunction => (
|
{this.props.contractFunctions.map(contractFunction => (
|
||||||
<List.Item key={contractFunction.result}>
|
<List.Item key={contractFunction.result}>
|
||||||
@ -72,7 +72,7 @@ class ContractFunction extends Component {
|
|||||||
</List.Item>
|
</List.Item>
|
||||||
))}
|
))}
|
||||||
</List>
|
</List>
|
||||||
</Card.Footer>
|
</Card.Footer>}
|
||||||
</Card>
|
</Card>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
</Grid.Row>
|
</Grid.Row>
|
||||||
@ -106,7 +106,7 @@ const ContractFunctions = (props) => {
|
|||||||
method={method}
|
method={method}
|
||||||
contractFunctions={filterContractFunctions(props.contractFunctions, contractProfile.name, method.name)}
|
contractFunctions={filterContractFunctions(props.contractFunctions, contractProfile.name, method.name)}
|
||||||
contractProfile={contractProfile}
|
contractProfile={contractProfile}
|
||||||
postContractFunction={props.postContractFunction} />)}
|
postContractFunction={props.postContractFunction}/>)}
|
||||||
</Page.Content>
|
</Page.Content>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
142
embark-ui/src/components/GasStation.js
Normal file
142
embark-ui/src/components/GasStation.js
Normal 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;
|
@ -3,10 +3,15 @@ import {connect} from 'react-redux';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import {withRouter} from 'react-router-dom';
|
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 ContractFunctions from '../components/ContractFunctions';
|
||||||
import DataWrapper from "../components/DataWrapper";
|
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 {
|
class ContractDeploymentContainer extends Component {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@ -16,14 +21,23 @@ class ContractDeploymentContainer extends Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<DataWrapper shouldRender={this.props.contractProfile !== undefined }
|
<React.Fragment>
|
||||||
{...this.props}
|
<DataWrapper shouldRender={this.props.contractProfile !== undefined}
|
||||||
render={({contractProfile, contractDeploys, postContractDeploy}) => (
|
{...this.props}
|
||||||
<ContractFunctions contractProfile={contractProfile}
|
render={({contractProfile, contractDeploys, postContractDeploy}) => (
|
||||||
contractFunctions={contractDeploys}
|
<ContractFunctions contractProfile={contractProfile}
|
||||||
onlyConstructor
|
contractFunctions={contractDeploys}
|
||||||
postContractFunction={postContractDeploy}/>
|
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 {
|
return {
|
||||||
contractProfile: getContractProfile(state, props.match.params.contractName),
|
contractProfile: getContractProfile(state, props.match.params.contractName),
|
||||||
contractDeploys: getContractDeploys(state, props.match.params.contractName),
|
contractDeploys: getContractDeploys(state, props.match.params.contractName),
|
||||||
|
gasStats: getGasStats(state),
|
||||||
error: state.errorMessage,
|
error: state.errorMessage,
|
||||||
loading: state.loading
|
loading: state.loading
|
||||||
};
|
};
|
||||||
|
@ -84,6 +84,10 @@ export function getVersions(state) {
|
|||||||
return state.entities.versions;
|
return state.entities.versions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getGasStats(state) {
|
||||||
|
return state.entities.gasStats[state.entities.gasStats.length - 1];
|
||||||
|
}
|
||||||
|
|
||||||
export function isWeb3Enabled(state) {
|
export function isWeb3Enabled(state) {
|
||||||
return Boolean(state.entities.versions.find((version) => version.name === 'web3'));
|
return Boolean(state.entities.versions.find((version) => version.name === 'web3'));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user