MyCrypto/common/components/TXMetaDataPanel/components/SimpleGas.tsx

167 lines
5.0 KiB
TypeScript

import React from 'react';
import Slider, { createSliderWithTooltip } from 'rc-slider';
import translate, { translateRaw } from 'translations';
import FeeSummary from './FeeSummary';
import './SimpleGas.scss';
import { AppState } from 'reducers';
import {
getGasLimitEstimationTimedOut,
getGasEstimationPending,
nonceRequestPending
} from 'selectors/transaction';
import { connect } from 'react-redux';
import { fetchGasEstimates, TFetchGasEstimates } from 'actions/gas';
import { getIsWeb3Node } from 'selectors/config';
import { getEstimates, getIsEstimating } from 'selectors/gas';
import { Wei, fromWei } from 'libs/units';
import { gasPriceDefaults } from 'config';
import { InlineSpinner } from 'components/ui/InlineSpinner';
import { TInputGasPrice } from 'actions/transaction';
const SliderWithTooltip = createSliderWithTooltip(Slider);
interface OwnProps {
gasPrice: AppState['transaction']['fields']['gasPrice'];
setGasPrice: TInputGasPrice;
inputGasPrice(rawGas: string): void;
}
interface StateProps {
gasEstimates: AppState['gas']['estimates'];
isGasEstimating: AppState['gas']['isEstimating'];
noncePending: boolean;
gasLimitPending: boolean;
isWeb3Node: boolean;
gasLimitEstimationTimedOut: boolean;
}
interface ActionProps {
fetchGasEstimates: TFetchGasEstimates;
}
type Props = OwnProps & StateProps & ActionProps;
class SimpleGas extends React.Component<Props> {
public componentDidMount() {
this.fixGasPrice();
this.props.fetchGasEstimates();
}
public componentWillReceiveProps(nextProps: Props) {
if (!this.props.gasEstimates && nextProps.gasEstimates) {
this.props.setGasPrice(nextProps.gasEstimates.fast.toString());
}
}
public render() {
const {
isGasEstimating,
gasEstimates,
gasPrice,
gasLimitEstimationTimedOut,
isWeb3Node,
noncePending,
gasLimitPending
} = this.props;
const bounds = {
max: gasEstimates ? gasEstimates.fastest : gasPriceDefaults.max,
min: gasEstimates ? gasEstimates.safeLow : gasPriceDefaults.min
};
return (
<div className="SimpleGas row form-group">
<div className="SimpleGas-title">
<div className="flex-wrapper">
<label>{translateRaw('Transaction Fee')} </label>
<div className="flex-spacer" />
<InlineSpinner active={noncePending || gasLimitPending} text="Calculating" />
</div>
</div>
{gasLimitEstimationTimedOut && (
<div className="prompt-toggle-gas-limit">
<p className="small">
{isWeb3Node
? "Couldn't calculate gas limit, if you know what you're doing, try setting manually in Advanced settings"
: "Couldn't calculate gas limit, try switching nodes"}
</p>
</div>
)}
<div className="SimpleGas-input-group">
<div className="SimpleGas-slider">
<SliderWithTooltip
onChange={this.handleSlider}
min={bounds.min}
max={bounds.max}
step={bounds.min < 1 ? 0.1 : 1}
value={this.getGasPriceGwei(gasPrice.value)}
tipFormatter={this.formatTooltip}
disabled={isGasEstimating}
/>
<div className="SimpleGas-slider-labels">
<span>{translate('Cheap')}</span>
<span>{translate('Fast')}</span>
</div>
</div>
<FeeSummary
gasPrice={gasPrice}
render={({ fee, usd }) => (
<span>
{fee} {usd && <span>/ ${usd}</span>}
</span>
)}
/>
</div>
</div>
);
}
private handleSlider = (gasGwei: number) => {
this.props.inputGasPrice(gasGwei.toString());
};
private fixGasPrice() {
const { gasPrice, gasEstimates } = this.props;
if (!gasEstimates) {
return;
}
// If the gas price is above or below our minimum, bring it in line
const gasPriceGwei = this.getGasPriceGwei(gasPrice.value);
if (gasPriceGwei < gasEstimates.safeLow) {
this.props.setGasPrice(gasEstimates.safeLow.toString());
} else if (gasPriceGwei > gasEstimates.fastest) {
this.props.setGasPrice(gasEstimates.fastest.toString());
}
}
private getGasPriceGwei(gasPriceValue: Wei) {
return parseFloat(fromWei(gasPriceValue, 'gwei'));
}
private formatTooltip = (gas: number) => {
const { gasEstimates } = this.props;
let recommended = '';
if (gasEstimates && !gasEstimates.isDefault && gas === gasEstimates.fast) {
recommended = '(Recommended)';
}
return `${gas} Gwei ${recommended}`;
};
}
export default connect(
(state: AppState): StateProps => ({
gasEstimates: getEstimates(state),
isGasEstimating: getIsEstimating(state),
noncePending: nonceRequestPending(state),
gasLimitPending: getGasEstimationPending(state),
gasLimitEstimationTimedOut: getGasLimitEstimationTimedOut(state),
isWeb3Node: getIsWeb3Node(state)
}),
{
fetchGasEstimates
}
)(SimpleGas);