mirror of
https://github.com/status-im/MyCrypto.git
synced 2025-02-19 22:38:12 +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;
|
type TReset = typeof reset;
|
||||||
const reset = (): ResetAction => ({ type: TypeKeys.RESET });
|
const reset = (payload: ResetAction['payload'] = { include: {}, exclude: {} }): ResetAction => ({
|
||||||
|
type: TypeKeys.RESET,
|
||||||
|
payload
|
||||||
|
});
|
||||||
|
|
||||||
export {
|
export {
|
||||||
TInputGasLimit,
|
TInputGasLimit,
|
||||||
|
@ -7,6 +7,9 @@ import { SignAction } from './sign';
|
|||||||
import { SwapAction } from './swap';
|
import { SwapAction } from './swap';
|
||||||
import { CurrentAction } from './current';
|
import { CurrentAction } from './current';
|
||||||
import { SendEverythingAction } from './sendEverything';
|
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 './broadcast';
|
||||||
export * from './fields';
|
export * from './fields';
|
||||||
@ -19,6 +22,18 @@ export * from './sendEverything';
|
|||||||
|
|
||||||
export interface ResetAction {
|
export interface ResetAction {
|
||||||
type: TypeKeys.RESET;
|
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 =
|
export type TransactionAction =
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
import { Reducer } from 'redux';
|
import { Reducer } from 'redux';
|
||||||
import { State } from './typings';
|
import { State } from './typings';
|
||||||
import { gasPricetoBase } from 'libs/units';
|
import { gasPricetoBase } from 'libs/units';
|
||||||
|
import { resetHOF } from 'reducers/transaction/shared';
|
||||||
|
|
||||||
const INITIAL_STATE: State = {
|
const INITIAL_STATE: State = {
|
||||||
to: { raw: '', value: null },
|
to: { raw: '', value: null },
|
||||||
@ -49,7 +50,7 @@ const tokenToToken = (
|
|||||||
{ payload: { decimal: _, tokenValue: __, ...rest } }: SwapTokenToTokenAction
|
{ payload: { decimal: _, tokenValue: __, ...rest } }: SwapTokenToTokenAction
|
||||||
): State => ({ ...state, ...rest });
|
): State => ({ ...state, ...rest });
|
||||||
|
|
||||||
const reset = (state: State): State => ({ ...INITIAL_STATE, gasPrice: state.gasPrice });
|
const reset = resetHOF('fields', INITIAL_STATE);
|
||||||
|
|
||||||
export const fields = (
|
export const fields = (
|
||||||
state: State = INITIAL_STATE,
|
state: State = INITIAL_STATE,
|
||||||
@ -75,7 +76,7 @@ export const fields = (
|
|||||||
case TK.TOKEN_TO_TOKEN_SWAP:
|
case TK.TOKEN_TO_TOKEN_SWAP:
|
||||||
return tokenToToken(state, action);
|
return tokenToToken(state, action);
|
||||||
case TK.RESET:
|
case TK.RESET:
|
||||||
return reset(state);
|
return reset(state, action);
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import {
|
|||||||
NetworkAction
|
NetworkAction
|
||||||
} from 'actions/transaction';
|
} from 'actions/transaction';
|
||||||
import { Reducer } from 'redux';
|
import { Reducer } from 'redux';
|
||||||
|
import { resetHOF } from 'reducers/transaction/shared';
|
||||||
|
|
||||||
const INITIAL_STATE: State = {
|
const INITIAL_STATE: State = {
|
||||||
unit: '',
|
unit: '',
|
||||||
@ -53,7 +54,7 @@ const tokenToToken = (
|
|||||||
{ payload: { data: _, to: __, ...rest } }: SwapTokenToTokenAction
|
{ payload: { data: _, to: __, ...rest } }: SwapTokenToTokenAction
|
||||||
): State => ({ ...state, ...rest });
|
): State => ({ ...state, ...rest });
|
||||||
|
|
||||||
const reset = () => INITIAL_STATE;
|
const reset = resetHOF('meta', INITIAL_STATE);
|
||||||
|
|
||||||
const unitMeta = (state: State, { payload }: SetUnitMetaAction): State => ({
|
const unitMeta = (state: State, { payload }: SetUnitMetaAction): State => ({
|
||||||
...state,
|
...state,
|
||||||
@ -81,7 +82,7 @@ export const meta = (
|
|||||||
case TK.TOKEN_TO_TOKEN_SWAP:
|
case TK.TOKEN_TO_TOKEN_SWAP:
|
||||||
return tokenToToken(state, action);
|
return tokenToToken(state, action);
|
||||||
case TK.RESET:
|
case TK.RESET:
|
||||||
return reset();
|
return reset(state, action);
|
||||||
default:
|
default:
|
||||||
return state;
|
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,
|
SignAction,
|
||||||
ResetAction
|
ResetAction
|
||||||
} from 'actions/transaction';
|
} from 'actions/transaction';
|
||||||
|
import { resetHOF } from 'reducers/transaction/shared';
|
||||||
|
|
||||||
const INITIAL_STATE: State = {
|
const INITIAL_STATE: State = {
|
||||||
local: { signedTransaction: null },
|
local: { signedTransaction: null },
|
||||||
@ -43,7 +44,7 @@ const signWeb3TranscationSucceeded = (
|
|||||||
|
|
||||||
const signTransactionFailed = () => INITIAL_STATE;
|
const signTransactionFailed = () => INITIAL_STATE;
|
||||||
|
|
||||||
const reset = () => INITIAL_STATE;
|
const reset = resetHOF('sign', INITIAL_STATE);
|
||||||
|
|
||||||
export const sign = (state: State = INITIAL_STATE, action: SignAction | ResetAction) => {
|
export const sign = (state: State = INITIAL_STATE, action: SignAction | ResetAction) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
@ -56,7 +57,7 @@ export const sign = (state: State = INITIAL_STATE, action: SignAction | ResetAct
|
|||||||
case TK.SIGN_TRANSACTION_FAILED:
|
case TK.SIGN_TRANSACTION_FAILED:
|
||||||
return signTransactionFailed();
|
return signTransactionFailed();
|
||||||
case TK.RESET:
|
case TK.RESET:
|
||||||
return reset();
|
return reset(state, action);
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import { meta } from './meta';
|
|||||||
import { network } from './network';
|
import { network } from './network';
|
||||||
import { signing } from './signing';
|
import { signing } from './signing';
|
||||||
import { sendEverything } from './sendEverything';
|
import { sendEverything } from './sendEverything';
|
||||||
import { reset, setDefaultUnit } from './reset';
|
import { reset } from './reset';
|
||||||
|
|
||||||
export function* transaction(): SagaIterator {
|
export function* transaction(): SagaIterator {
|
||||||
yield all([
|
yield all([
|
||||||
@ -18,7 +18,6 @@ export function* transaction(): SagaIterator {
|
|||||||
...network,
|
...network,
|
||||||
...signing,
|
...signing,
|
||||||
...sendEverything,
|
...sendEverything,
|
||||||
...reset,
|
...reset
|
||||||
setDefaultUnit
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { SagaIterator } from 'redux-saga';
|
import { SagaIterator } from 'redux-saga';
|
||||||
import { TypeKeys } from 'actions/wallet';
|
import { TypeKeys as WalletTypeKeys } from 'actions/wallet';
|
||||||
import { takeEvery, put, select } from 'redux-saga/effects';
|
import { takeEvery, put, take, race, fork, select } from 'redux-saga/effects';
|
||||||
import {
|
import {
|
||||||
reset as resetActionCreator,
|
|
||||||
setUnitMeta,
|
setUnitMeta,
|
||||||
TypeKeys as Constants
|
TypeKeys as TransactionTypeKeys,
|
||||||
|
reset as resetActionCreator,
|
||||||
|
ResetAction
|
||||||
} from 'actions/transaction';
|
} from 'actions/transaction';
|
||||||
import { getNetworkUnit } from 'selectors/config';
|
import { getNetworkUnit } from 'selectors/config';
|
||||||
|
|
||||||
@ -12,11 +13,68 @@ export function* resetTransactionState(): SagaIterator {
|
|||||||
yield put(resetActionCreator());
|
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);
|
const networkUnit = yield select(getNetworkUnit);
|
||||||
yield put(setUnitMeta(networkUnit));
|
yield put(setUnitMeta(networkUnit));
|
||||||
}
|
}
|
||||||
|
|
||||||
export const setDefaultUnit = takeEvery(Constants.RESET, setNetworkUnit);
|
export const reset = [
|
||||||
|
takeEvery([WalletTypeKeys.WALLET_RESET], resetTransactionState),
|
||||||
export const reset = [takeEvery([TypeKeys.WALLET_RESET], resetTransactionState)];
|
fork(watchTransactionState),
|
||||||
|
takeEvery(TransactionTypeKeys.RESET, setNetworkUnit)
|
||||||
|
];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user