Remove tx on state change (#1224)

* Clear serialized transaction on any change to transaction state

* Fix tsc errors

* remove console error

* Remove property mutations

* dont reset network unit when unit property isnt being reset
This commit is contained in:
HenryNguyen5 2018-03-02 01:28:50 -05:00 committed by Daniel Ternyak
parent 84319ab9a1
commit e9d719be52
8 changed files with 133 additions and 18 deletions

View File

@ -81,7 +81,10 @@ const setGasPriceField = (payload: SetGasPriceFieldAction['payload']): SetGasPri
});
type TReset = typeof reset;
const reset = (): ResetAction => ({ type: TypeKeys.RESET });
const reset = (payload: ResetAction['payload'] = { include: {}, exclude: {} }): ResetAction => ({
type: TypeKeys.RESET,
payload
});
export {
TInputGasLimit,

View File

@ -7,6 +7,9 @@ import { SignAction } from './sign';
import { SwapAction } from './swap';
import { CurrentAction } from './current';
import { SendEverythingAction } from './sendEverything';
import { State as FieldState } from 'reducers/transaction/fields';
import { State as MetaState } from 'reducers/transaction/meta';
import { State as SignState } from 'reducers/transaction/sign';
export * from './broadcast';
export * from './fields';
@ -19,6 +22,18 @@ export * from './sendEverything';
export interface ResetAction {
type: TypeKeys.RESET;
payload: {
include: {
fields?: (keyof FieldState)[];
meta?: (keyof MetaState)[];
sign?: (keyof SignState)[];
};
exclude: {
fields?: (keyof FieldState)[];
meta?: (keyof MetaState)[];
sign?: (keyof SignState)[];
};
};
}
export type TransactionAction =

View File

@ -11,6 +11,7 @@ import {
import { Reducer } from 'redux';
import { State } from './typings';
import { gasPricetoBase } from 'libs/units';
import { resetHOF } from 'reducers/transaction/shared';
const INITIAL_STATE: State = {
to: { raw: '', value: null },
@ -49,7 +50,7 @@ const tokenToToken = (
{ payload: { decimal: _, tokenValue: __, ...rest } }: SwapTokenToTokenAction
): State => ({ ...state, ...rest });
const reset = (state: State): State => ({ ...INITIAL_STATE, gasPrice: state.gasPrice });
const reset = resetHOF('fields', INITIAL_STATE);
export const fields = (
state: State = INITIAL_STATE,
@ -75,7 +76,7 @@ export const fields = (
case TK.TOKEN_TO_TOKEN_SWAP:
return tokenToToken(state, action);
case TK.RESET:
return reset(state);
return reset(state, action);
default:
return state;
}

View File

@ -12,6 +12,7 @@ import {
NetworkAction
} from 'actions/transaction';
import { Reducer } from 'redux';
import { resetHOF } from 'reducers/transaction/shared';
const INITIAL_STATE: State = {
unit: '',
@ -53,7 +54,7 @@ const tokenToToken = (
{ payload: { data: _, to: __, ...rest } }: SwapTokenToTokenAction
): State => ({ ...state, ...rest });
const reset = () => INITIAL_STATE;
const reset = resetHOF('meta', INITIAL_STATE);
const unitMeta = (state: State, { payload }: SetUnitMetaAction): State => ({
...state,
@ -81,7 +82,7 @@ export const meta = (
case TK.TOKEN_TO_TOKEN_SWAP:
return tokenToToken(state, action);
case TK.RESET:
return reset();
return reset(state, action);
default:
return state;
}

View File

@ -0,0 +1,37 @@
import { State } from './transaction';
import { Omit } from 'react-redux';
import { ResetAction } from 'actions/transaction';
export const resetHOF = (
reducerName: keyof (Omit<State, 'broadcast' | 'network'>),
initialState: State[typeof reducerName],
returnCb?: (
state: State[typeof reducerName],
returnedState: State[typeof reducerName]
) => State[typeof reducerName]
) => (state: State[typeof reducerName], { payload: { exclude, include } }: ResetAction) => {
const excludeFields = exclude[reducerName];
const includeFields = include[reducerName];
// sanity check
if (includeFields && excludeFields) {
throw Error('Cant have include and exclude fields at the same time');
}
const returnState = { ...initialState };
const stateCopy = { ...state };
if (includeFields) {
(includeFields as any[]).forEach(fieldName => {
stateCopy[fieldName] = returnState[fieldName];
});
return returnCb ? returnCb(state, returnState) : { ...stateCopy };
}
if (excludeFields) {
(excludeFields as any[]).forEach(fieldName => {
returnState[fieldName] = state[fieldName];
});
}
return returnCb ? returnCb(state, returnState) : returnState;
};

View File

@ -6,6 +6,7 @@ import {
SignAction,
ResetAction
} from 'actions/transaction';
import { resetHOF } from 'reducers/transaction/shared';
const INITIAL_STATE: State = {
local: { signedTransaction: null },
@ -43,7 +44,7 @@ const signWeb3TranscationSucceeded = (
const signTransactionFailed = () => INITIAL_STATE;
const reset = () => INITIAL_STATE;
const reset = resetHOF('sign', INITIAL_STATE);
export const sign = (state: State = INITIAL_STATE, action: SignAction | ResetAction) => {
switch (action.type) {
@ -56,7 +57,7 @@ export const sign = (state: State = INITIAL_STATE, action: SignAction | ResetAct
case TK.SIGN_TRANSACTION_FAILED:
return signTransactionFailed();
case TK.RESET:
return reset();
return reset(state, action);
default:
return state;
}

View File

@ -7,7 +7,7 @@ import { meta } from './meta';
import { network } from './network';
import { signing } from './signing';
import { sendEverything } from './sendEverything';
import { reset, setDefaultUnit } from './reset';
import { reset } from './reset';
export function* transaction(): SagaIterator {
yield all([
@ -18,7 +18,6 @@ export function* transaction(): SagaIterator {
...network,
...signing,
...sendEverything,
...reset,
setDefaultUnit
...reset
]);
}

View File

@ -1,10 +1,11 @@
import { SagaIterator } from 'redux-saga';
import { TypeKeys } from 'actions/wallet';
import { takeEvery, put, select } from 'redux-saga/effects';
import { TypeKeys as WalletTypeKeys } from 'actions/wallet';
import { takeEvery, put, take, race, fork, select } from 'redux-saga/effects';
import {
reset as resetActionCreator,
setUnitMeta,
TypeKeys as Constants
TypeKeys as TransactionTypeKeys,
reset as resetActionCreator,
ResetAction
} from 'actions/transaction';
import { getNetworkUnit } from 'selectors/config';
@ -12,11 +13,68 @@ export function* resetTransactionState(): SagaIterator {
yield put(resetActionCreator());
}
export function* setNetworkUnit(): SagaIterator {
/**
* After a transaction is signed, wait for any action that would result in the transaction state changing then fire off
* a handler that will remove the current serialized transaction so the user does not send a stale transaction
*/
export function* watchTransactionState(): SagaIterator {
while (true) {
// wait for transaction to be signed
yield take([
TransactionTypeKeys.SIGN_LOCAL_TRANSACTION_SUCCEEDED,
TransactionTypeKeys.SIGN_WEB3_TRANSACTION_SUCCEEDED
]);
const { bail } = yield race({
bail: take([
TransactionTypeKeys.RESET,
WalletTypeKeys.WALLET_RESET,
WalletTypeKeys.WALLET_RESET
]), // bail on actions that would wipe state
wipeState: take([
TransactionTypeKeys.CURRENT_TO_SET,
TransactionTypeKeys.CURRENT_VALUE_SET,
TransactionTypeKeys.GAS_LIMIT_FIELD_SET,
TransactionTypeKeys.GAS_PRICE_FIELD_SET,
TransactionTypeKeys.VALUE_FIELD_SET,
TransactionTypeKeys.DATA_FIELD_SET,
TransactionTypeKeys.NONCE_FIELD_SET,
TransactionTypeKeys.TO_FIELD_SET,
TransactionTypeKeys.TOKEN_TO_META_SET,
TransactionTypeKeys.TOKEN_VALUE_META_SET,
TransactionTypeKeys.UNIT_META_SET
]) // watch for any actions that would change transaction state
});
if (bail) {
continue;
}
yield put(
resetActionCreator({
exclude: {
fields: ['data', 'gasLimit', 'gasPrice', 'nonce', 'to', 'value'],
meta: ['decimal', 'from', 'previousUnit', 'tokenTo', 'tokenValue', 'unit']
},
include: {}
})
);
}
}
export function* setNetworkUnit({ payload: { exclude, include } }: ResetAction): SagaIterator {
if (exclude.meta && exclude.meta.includes('unit')) {
return;
}
if (include.meta && !include.meta.includes('unit')) {
return;
}
const networkUnit = yield select(getNetworkUnit);
yield put(setUnitMeta(networkUnit));
}
export const setDefaultUnit = takeEvery(Constants.RESET, setNetworkUnit);
export const reset = [takeEvery([TypeKeys.WALLET_RESET], resetTransactionState)];
export const reset = [
takeEvery([WalletTypeKeys.WALLET_RESET], resetTransactionState),
fork(watchTransactionState),
takeEvery(TransactionTypeKeys.RESET, setNetworkUnit)
];