conflict in saga
This commit is contained in:
parent
9d262e6a25
commit
5690c2e054
|
@ -200,17 +200,10 @@ export const files = {
|
|||
failure: (error) => action(FILES[FAILURE], {error})
|
||||
};
|
||||
|
||||
export const ETH_GAS = createRequestTypes('ETH_GAS');
|
||||
export const ethGas = {
|
||||
request: () => action(ETH_GAS[REQUEST]),
|
||||
success: (gasStats) => action(ETH_GAS[SUCCESS], {gasStats: [gasStats]}),
|
||||
failure: (error) => action(ETH_GAS[FAILURE], {error})
|
||||
};
|
||||
|
||||
export const GAS_ORACLE = createRequestTypes('GAS_ORACLE');
|
||||
export const gasOracle = {
|
||||
request: () => action(GAS_ORACLE[REQUEST]),
|
||||
success: (gasOracleStats) => action(GAS_ORACLE[SUCCESS], {gasOracleStats}),
|
||||
success: (gasOracleStats) => action(GAS_ORACLE[SUCCESS], {gasOracleStats: [gasOracleStats]}),
|
||||
failure: (error) => action(GAS_ORACLE[FAILURE], {error})
|
||||
};
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ export function fetchContractFile(payload) {
|
|||
}
|
||||
|
||||
export function getEthGasAPI() {
|
||||
return get('/json/ethgasAPI.json', {}, 'https://ethgasstation.info');
|
||||
return get('/blockchain/gas/oracle', {});
|
||||
}
|
||||
|
||||
export function fetchLastFiddle() {
|
||||
|
|
|
@ -4,8 +4,8 @@ import {connect} from 'react-redux';
|
|||
import {withRouter} from "react-router-dom";
|
||||
import {Card, Form, Grid, StampCard, Stamp} from 'tabler-react';
|
||||
import {CopyToClipboard} from 'react-copy-to-clipboard';
|
||||
import {listenToGasOracle} from "../actions";
|
||||
import {getOracleGasStats} from "../reducers/selectors";
|
||||
import {listenToGasOracle, gasOracle as ethGasAction} from "../actions";
|
||||
import {getGasStats, getOracleGasStats} from "../reducers/selectors";
|
||||
|
||||
const COLORS = {
|
||||
good: 'green',
|
||||
|
@ -16,42 +16,20 @@ const COLORS = {
|
|||
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,
|
||||
gasOracleSliderIndex: 0,
|
||||
copied: false
|
||||
};
|
||||
this.formattedGasStats = GasStation.formatGasStats(props.gasStats);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.props.fetchEthGas();
|
||||
if (!this.props.gasOracleStats.length) {
|
||||
this.props.listenToGasOracle();
|
||||
}
|
||||
}
|
||||
|
||||
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}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
getGasOracleFormatted() {
|
||||
const gasPrices = Object.keys(this.props.gasOracleStats);
|
||||
if (!gasPrices.length) {
|
||||
|
@ -59,9 +37,11 @@ class GasStation extends Component {
|
|||
}
|
||||
return gasPrices.map(gasPrice => {
|
||||
return {
|
||||
gasPrice: gasPrice,
|
||||
gasPrice,
|
||||
wait: this.props.gasOracleStats[gasPrice].averageWait
|
||||
};
|
||||
}).sort((a, b) => {
|
||||
return a.gasPrice - b.gasPrice;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -72,35 +52,38 @@ class GasStation extends Component {
|
|||
}
|
||||
|
||||
static getColorForWait(wait) {
|
||||
if (wait <= 1) {
|
||||
if (wait <= 60) {
|
||||
return COLORS.good;
|
||||
}
|
||||
if (wait <= 3) {
|
||||
if (wait <= 180) {
|
||||
return COLORS.medium;
|
||||
}
|
||||
return COLORS.bad;
|
||||
}
|
||||
|
||||
static getColorForPrice(gasPrice) {
|
||||
if (gasPrice <= 20) {
|
||||
if (gasPrice <= 20000000000) {
|
||||
return COLORS.good;
|
||||
}
|
||||
if (gasPrice <= 40) {
|
||||
if (gasPrice <= 40000000000) {
|
||||
return COLORS.medium;
|
||||
}
|
||||
return COLORS.bad;
|
||||
}
|
||||
|
||||
render() {
|
||||
const currentGasStep = this.formattedGasStats.gasSteps[this.state.gasSliderIndex];
|
||||
const formattedGasOracleStats = this.getGasOracleFormatted();
|
||||
const currentGasStep = formattedGasOracleStats[this.state.gasOracleSliderIndex];
|
||||
if (!formattedGasOracleStats.length) {
|
||||
return '';
|
||||
}
|
||||
return <Grid.Row>
|
||||
<Grid.Col>
|
||||
<Card>
|
||||
<Card.Header>
|
||||
<Card.Title>Gas Price Estimator (for Mainnet)</Card.Title>
|
||||
<Card.Title>Gas Price Estimator</Card.Title>
|
||||
<Card.Options>
|
||||
<CopyToClipboard text={currentGasStep.price / 10}
|
||||
<CopyToClipboard text={currentGasStep.gasPrice / 1000000000}
|
||||
onCopy={() => this.setState({copied: true})}
|
||||
title="Copy gas price to clipboard">
|
||||
<span><Stamp color="blue" icon="copy"/></span>
|
||||
|
@ -112,40 +95,31 @@ class GasStation extends Component {
|
|||
{this.state.copied && <p>Copied Gas Price</p>}
|
||||
<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 icon="sliders" color={GasStation.getColorForPrice(currentGasStep.gasPrice)}>
|
||||
{currentGasStep.gasPrice / 1000000000} Wei
|
||||
</StampCard>
|
||||
</Grid.Col>
|
||||
<Grid.Col lg={6} md={6} sm={12}>
|
||||
<StampCard icon="clock" color={GasStation.getColorForWait(currentGasStep.wait)}>
|
||||
{currentGasStep.wait} minutes
|
||||
{currentGasStep.wait} seconds
|
||||
</StampCard>
|
||||
</Grid.Col>
|
||||
</Grid.Row>
|
||||
|
||||
<Form.Group>
|
||||
<input type="range" className="slider"
|
||||
max={this.formattedGasStats.gasSteps.length - 1}
|
||||
min={0}
|
||||
step={1}
|
||||
value={this.state.gasSliderIndex}
|
||||
onChange={(e) => this.gasSliderChange(e, 'gasSliderIndex')}
|
||||
/>
|
||||
|
||||
{formattedGasOracleStats.length > 0 &&
|
||||
<input type="range" className="slider"
|
||||
max={formattedGasOracleStats.length - 1}
|
||||
min={0}
|
||||
step={1}
|
||||
value={this.state.gasOracleSliderIndex}
|
||||
onChange={(e) => this.gasSliderChange(e, 'gasOracleSliderIndex')}
|
||||
/>}
|
||||
/>
|
||||
</Form.Group>
|
||||
|
||||
<Grid.Row cards={true}>
|
||||
{/*<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
|
||||
Average Price: {this.formattedGasStats.average.price} Wei
|
||||
</StampCard>
|
||||
</Grid.Col>
|
||||
<Grid.Col lg={4} md={6} sm={12}>
|
||||
|
@ -158,7 +132,7 @@ class GasStation extends Component {
|
|||
Last Block: {this.formattedGasStats.blockNum}
|
||||
</StampCard>
|
||||
</Grid.Col>
|
||||
</Grid.Row>
|
||||
</Grid.Row>*/}
|
||||
</Card.Body>
|
||||
</Card>
|
||||
</Grid.Col>
|
||||
|
@ -167,20 +141,22 @@ class GasStation extends Component {
|
|||
}
|
||||
|
||||
GasStation.propTypes = {
|
||||
gasStats: PropTypes.object.isRequired,
|
||||
gasOracleStats: PropTypes.array,
|
||||
listenToGasOracle: PropTypes.func
|
||||
gasOracleStats: PropTypes.object,
|
||||
listenToGasOracle: PropTypes.func,
|
||||
fetchEthGas: PropTypes.func
|
||||
};
|
||||
|
||||
function mapStateToProps(state, _props) {
|
||||
return {
|
||||
gasOracleStats: getOracleGasStats(state)
|
||||
gasOracleStats: getOracleGasStats(state),
|
||||
gasStats: getGasStats(state)
|
||||
};
|
||||
}
|
||||
|
||||
export default withRouter(connect(
|
||||
mapStateToProps,
|
||||
{
|
||||
listenToGasOracle: listenToGasOracle
|
||||
listenToGasOracle: listenToGasOracle,
|
||||
fetchEthGas: ethGasAction.request
|
||||
}
|
||||
)(GasStation));
|
||||
|
|
|
@ -3,11 +3,7 @@ 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} from '../actions';
|
||||
import ContractFunctions from '../components/ContractFunctions';
|
||||
import DataWrapper from "../components/DataWrapper";
|
||||
import GasStation from "../components/GasStation";
|
||||
|
@ -16,7 +12,6 @@ import {getContractProfile, getContractDeploys, getGasStats} from "../reducers/s
|
|||
class ContractDeploymentContainer extends Component {
|
||||
componentDidMount() {
|
||||
this.props.fetchContractProfile(this.props.match.params.contractName);
|
||||
this.props.fetchEthGas();
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -30,12 +25,7 @@ class ContractDeploymentContainer extends Component {
|
|||
onlyConstructor
|
||||
postContractFunction={postContractDeploy}/>
|
||||
)}/>
|
||||
|
||||
<DataWrapper shouldRender={this.props.gasStats !== undefined}
|
||||
{...this.props}
|
||||
render={({gasStats}) => (
|
||||
<GasStation gasStats={gasStats}/>
|
||||
)}/>
|
||||
<GasStation/>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
@ -57,7 +47,6 @@ ContractDeploymentContainer.propTypes = {
|
|||
contractFunctions: PropTypes.arrayOf(PropTypes.object),
|
||||
postContractDeploy: PropTypes.func,
|
||||
fetchContractProfile: PropTypes.func,
|
||||
fetchEthGas: PropTypes.func,
|
||||
error: PropTypes.string
|
||||
};
|
||||
|
||||
|
@ -65,7 +54,6 @@ export default withRouter(connect(
|
|||
mapStateToProps,
|
||||
{
|
||||
fetchContractProfile: contractProfileAction.request,
|
||||
postContractDeploy: contractDeployAction.post,
|
||||
fetchEthGas: ethGasAction.request
|
||||
postContractDeploy: contractDeployAction.post
|
||||
}
|
||||
)(ContractDeploymentContainer));
|
||||
|
|
|
@ -3,20 +3,15 @@ import {connect} from 'react-redux';
|
|||
import PropTypes from 'prop-types';
|
||||
import {withRouter} from 'react-router-dom';
|
||||
|
||||
import {
|
||||
contractProfile as contractProfileAction,
|
||||
contractFunction as contractFunctionAction,
|
||||
ethGas as ethGasAction
|
||||
} from '../actions';
|
||||
import {contractProfile as contractProfileAction, contractFunction as contractFunctionAction} from '../actions';
|
||||
import ContractFunctions from '../components/ContractFunctions';
|
||||
import DataWrapper from "../components/DataWrapper";
|
||||
import GasStation from "../components/GasStation";
|
||||
import {getContractProfile, getContractFunctions, getGasStats} from "../reducers/selectors";
|
||||
import {getContractProfile, getContractFunctions} from "../reducers/selectors";
|
||||
|
||||
class ContractFunctionsContainer extends Component {
|
||||
componentDidMount() {
|
||||
this.props.fetchContractProfile(this.props.match.params.contractName);
|
||||
this.props.fetchEthGas();
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -32,8 +27,8 @@ class ContractFunctionsContainer extends Component {
|
|||
|
||||
<DataWrapper shouldRender={this.props.gasStats !== undefined}
|
||||
{...this.props}
|
||||
render={({gasStats}) => (
|
||||
<GasStation gasStats={gasStats}/>
|
||||
render={() => (
|
||||
<GasStation/>
|
||||
)}/>
|
||||
</React.Fragment>
|
||||
);
|
||||
|
@ -44,7 +39,6 @@ function mapStateToProps(state, props) {
|
|||
return {
|
||||
contractProfile: getContractProfile(state, props.match.params.contractName),
|
||||
contractFunctions: getContractFunctions(state, props.match.params.contractName),
|
||||
gasStats: getGasStats(state),
|
||||
error: state.errorMessage,
|
||||
loading: state.loading
|
||||
};
|
||||
|
@ -64,7 +58,6 @@ export default withRouter(connect(
|
|||
mapStateToProps,
|
||||
{
|
||||
fetchContractProfile: contractProfileAction.request,
|
||||
postContractFunction: contractFunctionAction.post,
|
||||
fetchEthGas: ethGasAction.request
|
||||
postContractFunction: contractFunctionAction.post
|
||||
}
|
||||
)(ContractFunctionsContainer));
|
||||
|
|
|
@ -42,7 +42,7 @@ export const sendMessage = doRequest.bind(null, messageSend, api.sendMessage);
|
|||
export const fetchEnsRecord = doRequest.bind(null, ensRecord, api.fetchEnsRecord);
|
||||
export const postEnsRecord = doRequest.bind(null, ensRecords, api.postEnsRecord);
|
||||
export const fetchFiles = doRequest.bind(null, files, api.fetchFiles);
|
||||
export const fetchEthGas = doRequest.bind(null, ethGas, api.getEthGasAPI);
|
||||
export const fetchEthGas = doRequest.bind(null, gasOracle, api.getEthGasAPI);
|
||||
|
||||
export function *watchFetchTransaction() {
|
||||
yield takeEvery(actions.TRANSACTION[actions.REQUEST], fetchTransaction);
|
||||
|
@ -153,7 +153,7 @@ export function *watchFetchFiles() {
|
|||
}
|
||||
|
||||
export function *watchFetchEthGas() {
|
||||
yield takeEvery(actions.ETH_GAS[actions.REQUEST], fetchEthGas);
|
||||
yield takeEvery(actions.GAS_ORACLE[actions.REQUEST], fetchEthGas);
|
||||
}
|
||||
|
||||
function createChannel(socket) {
|
||||
|
@ -212,7 +212,7 @@ export function *listenGasOracle() {
|
|||
const channel = yield call(createChannel, socket);
|
||||
while (true) {
|
||||
const gasOracleStats = yield take(channel);
|
||||
yield put(gasOracle.success([gasOracleStats]));
|
||||
yield put(gasOracle.success(gasOracleStats));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,13 @@ class TransactionTracker {
|
|||
|
||||
registerAPICalls() {
|
||||
const self = this;
|
||||
self.embark.registerAPICall(
|
||||
'get',
|
||||
'/embark-api/blockchain/gas/oracle',
|
||||
(req, res) => {
|
||||
res.send(self.calculateGasPriceSpeeds());
|
||||
}
|
||||
);
|
||||
self.embark.registerAPICall(
|
||||
'ws',
|
||||
'/embark-api/blockchain/gas/oracle',
|
||||
|
|
Loading…
Reference in New Issue