[FEATURE] Gas estimation for scheduling

This commit is contained in:
Daniel Kmak 2018-04-05 18:56:00 +02:00 committed by Bagaric
parent dde63beae3
commit 40be251e7b
5 changed files with 67 additions and 17 deletions

View File

@ -9,9 +9,14 @@ import { Input } from 'components/ui';
interface Props { interface Props {
customLabel?: string; customLabel?: string;
disabled?: boolean; disabled?: boolean;
hideGasCalculationSpinner?: boolean;
} }
export const GasLimitField: React.SFC<Props> = ({ customLabel, disabled }) => ( export const GasLimitField: React.SFC<Props> = ({
customLabel,
disabled,
hideGasCalculationSpinner
}) => (
<GasLimitFieldFactory <GasLimitFieldFactory
withProps={({ gasLimit: { raw }, onChange, readOnly, gasEstimationPending }) => ( withProps={({ gasLimit: { raw }, onChange, readOnly, gasEstimationPending }) => (
<div className="input-group-wrapper"> <div className="input-group-wrapper">
@ -19,7 +24,10 @@ export const GasLimitField: React.SFC<Props> = ({ customLabel, disabled }) => (
<div className="input-group-header"> <div className="input-group-header">
{customLabel ? customLabel : translate('TRANS_GAS')} {customLabel ? customLabel : translate('TRANS_GAS')}
<div className="flex-spacer" /> <div className="flex-spacer" />
<InlineSpinner active={gasEstimationPending} text="Calculating" /> <InlineSpinner
active={!hideGasCalculationSpinner && gasEstimationPending}
text="Calculating"
/>
</div> </div>
<Input <Input
className={gasLimitValidator(raw) ? 'is-valid' : 'is-invalid'} className={gasLimitValidator(raw) ? 'is-valid' : 'is-invalid'}

View File

@ -102,6 +102,7 @@ class AdvancedGas extends React.Component<Props, State> {
<GasLimitField <GasLimitField
customLabel={translateRaw('OFFLINE_STEP2_LABEL_4')} customLabel={translateRaw('OFFLINE_STEP2_LABEL_4')}
disabled={scheduling} disabled={scheduling}
hideGasCalculationSpinner={scheduling}
/> />
</div> </div>
)} )}

View File

@ -3,12 +3,17 @@ import React from 'react';
import { AppState } from 'reducers'; import { AppState } from 'reducers';
import { setScheduleGasLimitField, TSetScheduleGasLimitField } from 'actions/transaction'; import { setScheduleGasLimitField, TSetScheduleGasLimitField } from 'actions/transaction';
import { translateRaw } from 'translations'; import { translateRaw } from 'translations';
import { Input } from 'components/ui'; import { Input, InlineSpinner } from 'components/ui';
import { getScheduleGasLimit, isValidScheduleGasLimit } from 'selectors/transaction'; import {
getScheduleGasLimit,
isValidScheduleGasLimit,
getGasEstimationPending
} from 'selectors/transaction';
import { Wei } from 'libs/units'; import { Wei } from 'libs/units';
import { EAC_SCHEDULING_CONFIG } from 'libs/scheduling'; import { EAC_SCHEDULING_CONFIG } from 'libs/scheduling';
interface OwnProps { interface OwnProps {
gasEstimationPending: boolean;
scheduleGasLimit: any; scheduleGasLimit: any;
validScheduleGasLimit: boolean; validScheduleGasLimit: boolean;
} }
@ -21,12 +26,16 @@ type Props = OwnProps & DispatchProps;
class ScheduleGasLimitFieldClass extends React.Component<Props> { class ScheduleGasLimitFieldClass extends React.Component<Props> {
public render() { public render() {
const { scheduleGasLimit, validScheduleGasLimit } = this.props; const { gasEstimationPending, scheduleGasLimit, validScheduleGasLimit } = this.props;
return ( return (
<div className="input-group-wrapper"> <div className="input-group-wrapper">
<label className="input-group"> <label className="input-group">
<div className="input-group-header">{translateRaw('SCHEDULE_GAS_LIMIT')}</div> <div className="input-group-header">
{translateRaw('SCHEDULE_GAS_LIMIT')}
<div className="flex-spacer" />
<InlineSpinner active={gasEstimationPending} text="Calculating" />
</div>
<Input <Input
className={!!scheduleGasLimit.raw && !validScheduleGasLimit ? 'invalid' : ''} className={!!scheduleGasLimit.raw && !validScheduleGasLimit ? 'invalid' : ''}
type="number" type="number"
@ -51,6 +60,7 @@ class ScheduleGasLimitFieldClass extends React.Component<Props> {
export const ScheduleGasLimitField = connect( export const ScheduleGasLimitField = connect(
(state: AppState) => ({ (state: AppState) => ({
gasEstimationPending: getGasEstimationPending(state),
scheduleGasLimit: getScheduleGasLimit(state), scheduleGasLimit: getScheduleGasLimit(state),
validScheduleGasLimit: isValidScheduleGasLimit(state) validScheduleGasLimit: isValidScheduleGasLimit(state)
}), }),

View File

@ -15,10 +15,10 @@ import { INode } from 'libs/nodes/INode';
import { getNodeLib, getOffline, getAutoGasLimitEnabled } from 'selectors/config'; import { getNodeLib, getOffline, getAutoGasLimitEnabled } from 'selectors/config';
import { getWalletInst } from 'selectors/wallet'; import { getWalletInst } from 'selectors/wallet';
import { getTransaction, IGetTransaction, getCurrentToAddressMessage } from 'selectors/transaction'; import { getTransaction, IGetTransaction, getCurrentToAddressMessage } from 'selectors/transaction';
import { getSchedulingToggle } from 'containers/Tabs/ScheduleTransaction/selectors/fields';
import { import {
EstimateGasRequestedAction, EstimateGasRequestedAction,
setGasLimitField, setGasLimitField,
estimateGasFailed,
estimateGasTimedout, estimateGasTimedout,
estimateGasSucceeded, estimateGasSucceeded,
TypeKeys, TypeKeys,
@ -27,7 +27,10 @@ import {
SetDataFieldAction, SetDataFieldAction,
SwapEtherToTokenAction, SwapEtherToTokenAction,
SwapTokenToTokenAction, SwapTokenToTokenAction,
SwapTokenToEtherAction SwapTokenToEtherAction,
SetSchedulingToggleAction,
setScheduleGasLimitField,
estimateGasFailed
} from 'actions/transaction'; } from 'actions/transaction';
import { TypeKeys as ConfigTypeKeys, ToggleAutoGasLimitAction } from 'actions/config'; import { TypeKeys as ConfigTypeKeys, ToggleAutoGasLimitAction } from 'actions/config';
import { IWallet } from 'libs/wallet'; import { IWallet } from 'libs/wallet';
@ -104,7 +107,19 @@ export function* estimateGas(): SagaIterator {
timeout: call(delay, 10000) timeout: call(delay, 10000)
}); });
if (gasLimit) { if (gasLimit) {
yield put(setGasLimitField({ raw: gasLimit.toString(), value: gasLimit })); const gasSetOptions = {
raw: gasLimit.toString(),
value: gasLimit
};
const scheduling: SetSchedulingToggleAction['payload'] = yield select(getSchedulingToggle);
if (scheduling && scheduling.value) {
yield put(setScheduleGasLimitField(gasSetOptions));
} else {
yield put(setGasLimitField(gasSetOptions));
}
yield put(estimateGasSucceeded()); yield put(estimateGasSucceeded());
} else { } else {
yield put(estimateGasTimedout()); yield put(estimateGasTimedout());

View File

@ -4,13 +4,15 @@ import BN from 'bn.js';
import { getNodeLib, getOffline, getAutoGasLimitEnabled } from 'selectors/config'; import { getNodeLib, getOffline, getAutoGasLimitEnabled } from 'selectors/config';
import { getWalletInst } from 'selectors/wallet'; import { getWalletInst } from 'selectors/wallet';
import { getTransaction, getCurrentToAddressMessage } from 'selectors/transaction'; import { getTransaction, getCurrentToAddressMessage } from 'selectors/transaction';
import { getSchedulingToggle } from 'containers/Tabs/ScheduleTransaction/selectors/fields';
import { import {
setGasLimitField, setGasLimitField,
estimateGasFailed, estimateGasFailed,
estimateGasSucceeded, estimateGasSucceeded,
TypeKeys, TypeKeys,
estimateGasRequested, estimateGasRequested,
estimateGasTimedout estimateGasTimedout,
setScheduleGasLimitField
} from 'actions/transaction'; } from 'actions/transaction';
import { makeTransaction, getTransactionFields } from 'libs/transaction'; import { makeTransaction, getTransactionFields } from 'libs/transaction';
import { import {
@ -113,6 +115,10 @@ describe('estimateGas*', () => {
const unsuccessfulGasEstimationResult = { const unsuccessfulGasEstimationResult = {
gasLimit: null gasLimit: null
}; };
const gasSetOptions = {
raw: gasLimit.toString(),
value: gasLimit
};
const gens: { [name: string]: any } = {}; const gens: { [name: string]: any } = {};
gens.successCase = cloneableGenerator(estimateGas)(); gens.successCase = cloneableGenerator(estimateGas)();
@ -175,15 +181,25 @@ describe('estimateGas*', () => {
); );
}); });
it('should put setGasLimitField', () => { it('should select getSchedulingToggle', () => {
gens.timeOutCase = gens.successCase.clone(); gens.timeOutCase = gens.successCase.clone();
expect(gens.successCase.next(successfulGasEstimationResult).value).toEqual( expect(gens.successCase.next(successfulGasEstimationResult).value).toEqual(
put( select(getSchedulingToggle)
setGasLimitField({ );
raw: gasLimit.toString(), });
value: gasLimit
}) it('should put setGasLimitField', () => {
) gens.scheduleCase = gens.successCase.clone();
const notScheduling = null as any;
expect(gens.successCase.next(notScheduling).value).toEqual(
put(setGasLimitField(gasSetOptions))
);
});
it('should put setScheduleGasLimitField', () => {
const scheduling = { value: true } as any;
expect(gens.scheduleCase.next(scheduling).value).toEqual(
put(setScheduleGasLimitField(gasSetOptions))
); );
}); });