remove device instances with different "passphrase_protection" settings

while DEVICE.CONNECT event
pull/2/merge
Szymon Lesisz 6 years ago
parent 1e89993727
commit 46c1f8b2b7

@ -3,8 +3,10 @@
import { LOCATION_CHANGE } from 'react-router-redux'; import { LOCATION_CHANGE } from 'react-router-redux';
import * as WALLET from './constants/wallet'; import * as WALLET from './constants/wallet';
import * as CONNECT from './constants/TrezorConnect';
import * as stateUtils from '../reducers/utils'; import * as stateUtils from '../reducers/utils';
import type { Device } from 'trezor-connect';
import type import type
{ {
Account, Account,
@ -12,7 +14,6 @@ import type
Discovery, Discovery,
Token, Token,
Web3Instance, Web3Instance,
TrezorDevice, TrezorDevice,
RouterLocationState, RouterLocationState,
ThunkAction, ThunkAction,
@ -41,6 +42,9 @@ export type WalletAction = {
} | { } | {
type: typeof WALLET.UPDATE_SELECTED_DEVICE, type: typeof WALLET.UPDATE_SELECTED_DEVICE,
device: TrezorDevice device: TrezorDevice
} | {
type: typeof WALLET.CLEAR_UNAVAILABLE_DEVICE_DATA,
devices: Array<TrezorDevice>
} }
export const init = (): ThunkAction => { export const init = (): ThunkAction => {
@ -70,6 +74,32 @@ export const toggleDeviceDropdown = (opened: boolean): WalletAction => {
} }
} }
// This method will be called after each DEVICE.CONNECT action
// if connected device has different "passphrase_protection" settings than saved instances
// all saved instances will be removed immediately inside DevicesReducer
// This method will clear leftovers associated with removed instances from reducers.
// (DiscoveryReducer, AccountReducer, TokensReducer)
export const clearUnavailableDevicesData = (prevState: State, device: Device): ThunkAction => {
return (dispatch: Dispatch, getState: GetState): void => {
if (!device.features) return;
const affectedDevices = prevState.devices.filter(d =>
d.features
&& d.features.device_id === device.features.device_id
&& d.features.passphrase_protection !== device.features.passphrase_protection
);
if (affectedDevices.length > 0) {
dispatch({
type: WALLET.CLEAR_UNAVAILABLE_DEVICE_DATA,
devices: affectedDevices,
})
}
}
}
export const updateSelectedValues = (prevState: State, action: Action): AsyncAction => { export const updateSelectedValues = (prevState: State, action: Action): AsyncAction => {
return async (dispatch: Dispatch, getState: GetState): Promise<void> => { return async (dispatch: Dispatch, getState: GetState): Promise<void> => {

@ -8,3 +8,5 @@ export const ONLINE_STATUS: 'wallet__online_status' = 'wallet__online_status';
export const SET_SELECTED_DEVICE: 'wallet__set_selected_device' = 'wallet__set_selected_device'; export const SET_SELECTED_DEVICE: 'wallet__set_selected_device' = 'wallet__set_selected_device';
export const UPDATE_SELECTED_DEVICE: 'wallet__update_selected_device' = 'wallet__update_selected_device'; export const UPDATE_SELECTED_DEVICE: 'wallet__update_selected_device' = 'wallet__update_selected_device';
export const CLEAR_UNAVAILABLE_DEVICE_DATA: 'wallet__clear_unavailable_device_data' = 'wallet__clear_unavailable_device_data';

@ -2,6 +2,7 @@
'use strict'; 'use strict';
import * as CONNECT from '../actions/constants/TrezorConnect'; import * as CONNECT from '../actions/constants/TrezorConnect';
import * as WALLET from '../actions/constants/wallet';
import * as ACCOUNT from '../actions/constants/account'; import * as ACCOUNT from '../actions/constants/account';
import type { Action, TrezorDevice } from '~/flowtype'; import type { Action, TrezorDevice } from '~/flowtype';
@ -71,6 +72,14 @@ const removeAccounts = (state: State, device: TrezorDevice): State => {
return state.filter(account => account.deviceState !== device.state); return state.filter(account => account.deviceState !== device.state);
} }
const clear = (state: State, devices: Array<TrezorDevice>): State => {
let newState: State = [ ...state ];
devices.forEach(d => {
newState = removeAccounts(newState, d);
});
return newState;
}
const setBalance = (state: State, action: AccountSetBalanceAction): State => { const setBalance = (state: State, action: AccountSetBalanceAction): State => {
const index: number = state.findIndex(account => account.address === action.address && account.network === action.network && account.deviceState === action.deviceState); const index: number = state.findIndex(account => account.address === action.address && account.network === action.network && account.deviceState === action.deviceState);
const newState: State = [ ...state ]; const newState: State = [ ...state ];
@ -98,6 +107,9 @@ export default (state: State = initialState, action: Action): State => {
case CONNECT.FORGET_SINGLE : case CONNECT.FORGET_SINGLE :
return removeAccounts(state, action.device); return removeAccounts(state, action.device);
case WALLET.CLEAR_UNAVAILABLE_DEVICE_DATA :
return clear(state, action.devices);
//case CONNECT.FORGET_SINGLE : //case CONNECT.FORGET_SINGLE :
// return forgetAccounts(state, action); // return forgetAccounts(state, action);

@ -89,28 +89,35 @@ const addDevice = (state: State, device: Device): State => {
if (affectedDevices.length > 0 ) { if (affectedDevices.length > 0 ) {
// check if freshly added device has different "passphrase_protection" settings // check if freshly added device has different "passphrase_protection" settings
let hasDifferentPassphraseSettings: boolean = false; // let hasDifferentPassphraseSettings: boolean = false;
let hasInstancesWithPassphraseSettings: boolean = false; // let hasInstancesWithPassphraseSettings: boolean = false;
const changedDevices: Array<TrezorDevice> = affectedDevices.map(d => { // const changedDevices: Array<TrezorDevice> = affectedDevices.map(d => {
if (d.features && d.features.passphrase_protection === device.features.passphrase_protection) { // if (d.features && d.features.passphrase_protection === device.features.passphrase_protection) {
hasInstancesWithPassphraseSettings = true; // hasInstancesWithPassphraseSettings = true;
return mergeDevices(d, { ...device, connected: true, available: true } ); // return mergeDevices(d, { ...device, connected: true, available: true } );
} else { // } else {
hasDifferentPassphraseSettings = true; // hasDifferentPassphraseSettings = true;
d.connected = true; // d.connected = true;
d.available = false; // d.available = false;
return d; // return d;
} // }
}); // });
// edge case: freshly connected device has different "passphrase_protection" than saved instances // edge case: freshly connected device has different "passphrase_protection" than saved instances
// need to automatically create another instance with default instance name // need to automatically create another instance with default instance name
if (hasDifferentPassphraseSettings && !hasInstancesWithPassphraseSettings) { // if (hasDifferentPassphraseSettings && !hasInstancesWithPassphraseSettings) {
const instance = getNewInstance(affectedDevices, device); // const instance = getNewInstance(affectedDevices, device);
// newDevice.instance = instance;
// newDevice.instanceLabel = `${device.label} (${instance})`;
newDevice.instance = instance; // changedDevices.push(newDevice);
newDevice.instanceLabel = `${device.label} (${instance})`; // }
const changedDevices: Array<TrezorDevice> = affectedDevices.filter(d => d.features && d.features.passphrase_protection === device.features.passphrase_protection).map(d => {
return mergeDevices(d, { ...device, connected: true, available: true } );
});
if (changedDevices.length !== affectedDevices.length) {
changedDevices.push(newDevice); changedDevices.push(newDevice);
} }

@ -6,6 +6,7 @@ import HDKey from 'hdkey';
import * as DISCOVERY from '../actions/constants/discovery'; import * as DISCOVERY from '../actions/constants/discovery';
import * as ACCOUNT from '../actions/constants/account'; import * as ACCOUNT from '../actions/constants/account';
import * as CONNECT from '../actions/constants/TrezorConnect'; import * as CONNECT from '../actions/constants/TrezorConnect';
import * as WALLET from '../actions/constants/wallet';
import type { Action, TrezorDevice } from '~/flowtype'; import type { Action, TrezorDevice } from '~/flowtype';
import type { import type {
@ -87,6 +88,14 @@ const forgetDiscovery = (state: State, device: TrezorDevice): State => {
return state.filter(d => d.deviceState !== device.state); return state.filter(d => d.deviceState !== device.state);
} }
const clear = (state: State, devices: Array<TrezorDevice>): State => {
let newState: State = [ ...state ];
devices.forEach(d => {
newState = forgetDiscovery(newState, d);
});
return newState;
}
const stop = (state: State, action: DiscoveryStopAction): State => { const stop = (state: State, action: DiscoveryStopAction): State => {
const newState: State = [ ...state ]; const newState: State = [ ...state ];
return newState.map( (d: Discovery) => { return newState.map( (d: Discovery) => {
@ -184,6 +193,8 @@ export default function discovery(state: State = initialState, action: Action):
case CONNECT.FORGET : case CONNECT.FORGET :
case CONNECT.FORGET_SINGLE : case CONNECT.FORGET_SINGLE :
return forgetDiscovery(state, action.device); return forgetDiscovery(state, action.device);
case WALLET.CLEAR_UNAVAILABLE_DEVICE_DATA :
return clear(state, action.devices);
default: default:
return state; return state;

@ -2,6 +2,7 @@
'use strict'; 'use strict';
import * as CONNECT from '../actions/constants/TrezorConnect'; import * as CONNECT from '../actions/constants/TrezorConnect';
import * as WALLET from '../actions/constants/wallet';
import * as TOKEN from '../actions/constants/token'; import * as TOKEN from '../actions/constants/token';
import type { Action, TrezorDevice } from '~/flowtype'; import type { Action, TrezorDevice } from '~/flowtype';
@ -43,7 +44,7 @@ export const findAccountTokens = (state: Array<Token>, account: Account): Array<
// } // }
const create = (state: State, token: Token): State => { const create = (state: State, token: Token): State => {
const newState: Array<Token> = [ ...state ]; const newState: State = [ ...state ];
newState.push(token); newState.push(token);
return newState; return newState;
} }
@ -52,6 +53,14 @@ const forget = (state: State, device: TrezorDevice): State => {
return state.filter(t => t.deviceState !== device.state); return state.filter(t => t.deviceState !== device.state);
} }
const clear = (state: State, devices: Array<TrezorDevice>): State => {
let newState: State = [ ...state ];
devices.forEach(d => {
newState = forget(newState, d);
});
return newState;
}
const remove = (state: State, token: Token): State => { const remove = (state: State, token: Token): State => {
return state.filter(t => { return state.filter(t => {
return !(t.ethAddress === token.ethAddress && t.address === token.address && t.deviceState === token.deviceState); return !(t.ethAddress === token.ethAddress && t.address === token.address && t.deviceState === token.deviceState);
@ -76,6 +85,9 @@ export default (state: State = initialState, action: Action): State => {
case CONNECT.FORGET_SINGLE : case CONNECT.FORGET_SINGLE :
return forget(state, action.device); return forget(state, action.device);
case WALLET.CLEAR_UNAVAILABLE_DEVICE_DATA :
return clear(state, action.devices);
default: default:
return state; return state;
} }

@ -1,6 +1,7 @@
/* @flow */ /* @flow */
'use strict'; 'use strict';
import { DEVICE } from 'trezor-connect';
import { LOCATION_CHANGE } from 'react-router-redux'; import { LOCATION_CHANGE } from 'react-router-redux';
import * as WALLET from '../actions/constants/wallet'; import * as WALLET from '../actions/constants/wallet';
import * as SEND from '../actions/constants/wallet'; import * as SEND from '../actions/constants/wallet';
@ -42,6 +43,10 @@ const WalletService: Middleware = (api: MiddlewareAPI) => (next: MiddlewareDispa
// pass action // pass action
next(action); next(action);
if (action.type === DEVICE.CONNECT) {
api.dispatch( WalletActions.clearUnavailableDevicesData(prevState, action.device) );
}
// update common values in WallerReducer // update common values in WallerReducer
api.dispatch( WalletActions.updateSelectedValues(prevState, action) ); api.dispatch( WalletActions.updateSelectedValues(prevState, action) );

Loading…
Cancel
Save