Don't refresh on network change (#1144)
* Configure sagas and components to react to network switch. * tscheck * Update tests with new behavior. * tscheck * Log out of wallet on network change. * Fix up test.
This commit is contained in:
parent
33f5ede22a
commit
1b6143e457
|
@ -81,11 +81,12 @@ class EquivalentValues extends React.Component<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentWillReceiveProps(nextProps: Props) {
|
public componentWillReceiveProps(nextProps: Props) {
|
||||||
const { balance, tokenBalances, isOffline } = this.props;
|
const { balance, tokenBalances, isOffline, network } = this.props;
|
||||||
if (
|
if (
|
||||||
nextProps.balance !== balance ||
|
nextProps.balance !== balance ||
|
||||||
nextProps.tokenBalances !== tokenBalances ||
|
nextProps.tokenBalances !== tokenBalances ||
|
||||||
nextProps.isOffline !== isOffline
|
nextProps.isOffline !== isOffline ||
|
||||||
|
nextProps.network.unit !== network.unit
|
||||||
) {
|
) {
|
||||||
const defaultOption = this.defaultOption(
|
const defaultOption = this.defaultOption(
|
||||||
nextProps.balance,
|
nextProps.balance,
|
||||||
|
@ -288,7 +289,8 @@ class EquivalentValues extends React.Component<Props, State> {
|
||||||
const currencies = tokenBalances
|
const currencies = tokenBalances
|
||||||
.filter(tk => !tk.balance.isZero())
|
.filter(tk => !tk.balance.isZero())
|
||||||
.map(tk => tk.symbol)
|
.map(tk => tk.symbol)
|
||||||
.sort();
|
.sort()
|
||||||
|
.concat([props.network.unit]);
|
||||||
|
|
||||||
// If it's the same currencies as we have, skip it
|
// If it's the same currencies as we have, skip it
|
||||||
if (this.requestedCurrencies && currencies.join() === this.requestedCurrencies.join()) {
|
if (this.requestedCurrencies && currencies.join() === this.requestedCurrencies.join()) {
|
||||||
|
|
|
@ -76,7 +76,10 @@ class TXMetaDataPanel extends React.Component<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentWillReceiveProps(nextProps: Props) {
|
public componentWillReceiveProps(nextProps: Props) {
|
||||||
if (this.props.offline && !nextProps.offline) {
|
if (
|
||||||
|
(this.props.offline && !nextProps.offline) ||
|
||||||
|
this.props.network.unit !== nextProps.network.unit
|
||||||
|
) {
|
||||||
this.props.fetchCCRates([this.props.network.unit]);
|
this.props.fetchCCRates([this.props.network.unit]);
|
||||||
}
|
}
|
||||||
if (this.props.gasPrice !== nextProps.gasPrice) {
|
if (this.props.gasPrice !== nextProps.gasPrice) {
|
||||||
|
|
|
@ -46,6 +46,12 @@ class LedgerNanoSDecryptClass extends PureComponent<Props, State> {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public componentWillReceiveProps(nextProps: Props) {
|
||||||
|
if (this.props.dPath !== nextProps.dPath) {
|
||||||
|
this.setState({ dPath: nextProps.dPath.value });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const { dPath, publicKey, chainCode, error, isLoading, showTip } = this.state;
|
const { dPath, publicKey, chainCode, error, isLoading, showTip } = this.state;
|
||||||
const showErr = error ? 'is-showing' : '';
|
const showErr = error ? 'is-showing' : '';
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { connect } from 'react-redux';
|
||||||
import { getSingleDPath, getPaths } from 'selectors/config/wallet';
|
import { getSingleDPath, getPaths } from 'selectors/config/wallet';
|
||||||
import { TogglablePassword } from 'components';
|
import { TogglablePassword } from 'components';
|
||||||
|
|
||||||
interface Props {
|
interface OwnProps {
|
||||||
onUnlock(param: any): void;
|
onUnlock(param: any): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,8 @@ interface StateProps {
|
||||||
dPaths: DPath[];
|
dPaths: DPath[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Props = OwnProps & StateProps;
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
phrase: string;
|
phrase: string;
|
||||||
formattedPhrase: string;
|
formattedPhrase: string;
|
||||||
|
@ -26,7 +28,7 @@ interface State {
|
||||||
dPath: string;
|
dPath: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MnemonicDecryptClass extends PureComponent<Props & StateProps, State> {
|
class MnemonicDecryptClass extends PureComponent<Props, State> {
|
||||||
public state: State = {
|
public state: State = {
|
||||||
phrase: '',
|
phrase: '',
|
||||||
formattedPhrase: '',
|
formattedPhrase: '',
|
||||||
|
@ -35,6 +37,12 @@ class MnemonicDecryptClass extends PureComponent<Props & StateProps, State> {
|
||||||
dPath: this.props.dPath.value
|
dPath: this.props.dPath.value
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public componentWillReceiveProps(nextProps: Props) {
|
||||||
|
if (this.props.dPath !== nextProps.dPath) {
|
||||||
|
this.setState({ dPath: nextProps.dPath.value });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const { phrase, formattedPhrase, seed, dPath, pass } = this.state;
|
const { phrase, formattedPhrase, seed, dPath, pass } = this.state;
|
||||||
const isValidMnemonic = validateMnemonic(formattedPhrase);
|
const isValidMnemonic = validateMnemonic(formattedPhrase);
|
||||||
|
|
|
@ -40,6 +40,12 @@ class TrezorDecryptClass extends PureComponent<Props, State> {
|
||||||
isLoading: false
|
isLoading: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public componentWillReceiveProps(nextProps: Props) {
|
||||||
|
if (this.props.dPath !== nextProps.dPath) {
|
||||||
|
this.setState({ dPath: nextProps.dPath.value });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const { dPath, publicKey, chainCode, error, isLoading } = this.state;
|
const { dPath, publicKey, chainCode, error, isLoading } = this.state;
|
||||||
const showErr = error ? 'is-showing' : '';
|
const showErr = error ? 'is-showing' : '';
|
||||||
|
|
|
@ -30,10 +30,10 @@ import {
|
||||||
ChangeNodeIntentAction
|
ChangeNodeIntentAction
|
||||||
} from 'actions/config';
|
} from 'actions/config';
|
||||||
import { showNotification } from 'actions/notifications';
|
import { showNotification } from 'actions/notifications';
|
||||||
|
import { resetWallet } from 'actions/wallet';
|
||||||
import { translateRaw } from 'translations';
|
import { translateRaw } from 'translations';
|
||||||
import { StaticNodeConfig, CustomNodeConfig, NodeConfig } from 'types/node';
|
import { StaticNodeConfig, CustomNodeConfig, NodeConfig } from 'types/node';
|
||||||
import { CustomNetworkConfig, StaticNetworkConfig } from 'types/network';
|
import { CustomNetworkConfig, StaticNetworkConfig } from 'types/network';
|
||||||
import { Web3Service } from 'libs/nodes/web3';
|
|
||||||
|
|
||||||
let hasCheckedOnline = false;
|
let hasCheckedOnline = false;
|
||||||
export function* pollOfflineStatus(): SagaIterator {
|
export function* pollOfflineStatus(): SagaIterator {
|
||||||
|
@ -168,18 +168,8 @@ export function* handleNodeChangeIntent({
|
||||||
yield put(setLatestBlock(currentBlock));
|
yield put(setLatestBlock(currentBlock));
|
||||||
yield put(changeNode({ networkId: nextNodeConfig.network, nodeId: nodeIdToSwitchTo }));
|
yield put(changeNode({ networkId: nextNodeConfig.network, nodeId: nodeIdToSwitchTo }));
|
||||||
|
|
||||||
// TODO - re-enable once DeterministicWallet state is fixed to flush properly.
|
if (currentConfig.network !== nextNodeConfig.network) {
|
||||||
// DeterministicWallet keeps path related state we need to flush before we can stop reloading
|
yield fork(handleNewNetwork);
|
||||||
|
|
||||||
// const currentWallet: IWallet | null = yield select(getWalletInst);
|
|
||||||
// if there's no wallet, do not reload as there's no component state to resync
|
|
||||||
// if (currentWallet && currentConfig.network !== actionConfig.network) {
|
|
||||||
|
|
||||||
const isNewNetwork = currentConfig.network !== nextNodeConfig.network;
|
|
||||||
const newIsWeb3 = nextNodeConfig.service === Web3Service;
|
|
||||||
// don't reload when web3 is selected; node will automatically re-set and state is not an issue here
|
|
||||||
if (isNewNetwork && !newIsWeb3) {
|
|
||||||
yield call(reload);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,6 +177,10 @@ export function* switchToNewNode(action: AddCustomNodeAction): SagaIterator {
|
||||||
yield put(changeNodeIntent(action.payload.id));
|
yield put(changeNodeIntent(action.payload.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function* handleNewNetwork() {
|
||||||
|
yield put(resetWallet());
|
||||||
|
}
|
||||||
|
|
||||||
export const node = [
|
export const node = [
|
||||||
takeEvery(TypeKeys.CONFIG_NODE_CHANGE_INTENT, handleNodeChangeIntent),
|
takeEvery(TypeKeys.CONFIG_NODE_CHANGE_INTENT, handleNodeChangeIntent),
|
||||||
takeLatest(TypeKeys.CONFIG_POLL_OFFLINE_STATUS, handlePollOfflineStatus),
|
takeLatest(TypeKeys.CONFIG_POLL_OFFLINE_STATUS, handlePollOfflineStatus),
|
||||||
|
|
|
@ -14,13 +14,10 @@ export function* handleNonceRequest(): SagaIterator {
|
||||||
const walletInst: AppState['wallet']['inst'] = yield select(getWalletInst);
|
const walletInst: AppState['wallet']['inst'] = yield select(getWalletInst);
|
||||||
const isOffline: boolean = yield select(getOffline);
|
const isOffline: boolean = yield select(getOffline);
|
||||||
try {
|
try {
|
||||||
if (isOffline) {
|
if (isOffline || !walletInst) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!walletInst) {
|
|
||||||
throw Error();
|
|
||||||
}
|
|
||||||
const fromAddress: string = yield apply(walletInst, walletInst.getAddressString);
|
const fromAddress: string = yield apply(walletInst, walletInst.getAddressString);
|
||||||
|
|
||||||
const retrievedNonce: string = yield apply(nodeLib, nodeLib.getTransactionCount, [fromAddress]);
|
const retrievedNonce: string = yield apply(nodeLib, nodeLib.getTransactionCount, [fromAddress]);
|
||||||
|
|
|
@ -7,7 +7,7 @@ import {
|
||||||
handleNodeChangeIntent,
|
handleNodeChangeIntent,
|
||||||
handlePollOfflineStatus,
|
handlePollOfflineStatus,
|
||||||
pollOfflineStatus,
|
pollOfflineStatus,
|
||||||
reload
|
handleNewNetwork
|
||||||
} from 'sagas/config/node';
|
} from 'sagas/config/node';
|
||||||
import {
|
import {
|
||||||
getNodeId,
|
getNodeId,
|
||||||
|
@ -213,9 +213,8 @@ describe('handleNodeChangeIntent*', () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call reload if network is new', () => {
|
it('should fork handleNewNetwork', () => {
|
||||||
expect(data.gen.next().value).toEqual(call(reload));
|
expect(data.gen.next().value).toEqual(fork(handleNewNetwork));
|
||||||
expect(data.gen.next().done).toEqual(true);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be done', () => {
|
it('should be done', () => {
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import { getNonceSucceeded, getNonceFailed, inputNonce } from 'actions/transaction';
|
import { getNonceSucceeded, inputNonce } from 'actions/transaction';
|
||||||
import { apply, put, select, fork, take, cancel } from 'redux-saga/effects';
|
import { apply, put, select, fork, take, cancel } from 'redux-saga/effects';
|
||||||
import { getNodeLib, getOffline } from 'selectors/config';
|
import { getNodeLib, getOffline } from 'selectors/config';
|
||||||
import { getWalletInst } from 'selectors/wallet';
|
import { getWalletInst } from 'selectors/wallet';
|
||||||
import { showNotification } from 'actions/notifications';
|
|
||||||
import { handleNonceRequest, handleNonceRequestWrapper } from 'sagas/transaction/network/nonce';
|
import { handleNonceRequest, handleNonceRequestWrapper } from 'sagas/transaction/network/nonce';
|
||||||
import { cloneableGenerator, createMockTask } from 'redux-saga/utils';
|
import { cloneableGenerator, createMockTask } from 'redux-saga/utils';
|
||||||
import { TypeKeys as WalletTK } from 'actions/wallet';
|
import { TypeKeys as WalletTK } from 'actions/wallet';
|
||||||
|
@ -41,14 +40,10 @@ describe('handleNonceRequest*', () => {
|
||||||
expect(gens.gen.next(nodeLib).value).toEqual(select(getWalletInst));
|
expect(gens.gen.next(nodeLib).value).toEqual(select(getWalletInst));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle being called without wallet inst correctly', () => {
|
it('should exit if being called without a wallet inst', () => {
|
||||||
gens.noWallet = gens.gen.clone();
|
gens.noWallet = gens.gen.clone();
|
||||||
gens.noWallet.next();
|
gens.noWallet.next(null); // No wallet inst
|
||||||
expect(gens.noWallet.next(offline).value).toEqual(
|
expect(gens.noWallet.next(offline).done).toEqual(true);
|
||||||
put(showNotification('warning', 'Your addresses nonce could not be fetched'))
|
|
||||||
);
|
|
||||||
expect(gens.noWallet.next().value).toEqual(put(getNonceFailed()));
|
|
||||||
expect(gens.noWallet.next().done).toEqual(true);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should select getOffline', () => {
|
it('should select getOffline', () => {
|
||||||
|
|
Loading…
Reference in New Issue