mirror of
https://github.com/status-im/MyCrypto.git
synced 2025-02-16 21:16:35 +00:00
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:
parent
84319ab9a1
commit
e9d719be52
@ -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,
|
||||
|
@ -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 =
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
37
common/reducers/transaction/shared.ts
Normal file
37
common/reducers/transaction/shared.ts
Normal 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;
|
||||
};
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
]);
|
||||
}
|
||||
|
@ -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)
|
||||
];
|
||||
|
Loading…
x
Reference in New Issue
Block a user