You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
trezor-wallet/src/js/reducers/DiscoveryReducer.js

192 lines
5.6 KiB

/* @flow */
'use strict';
import HDKey from 'hdkey';
import * as DISCOVERY from '../actions/constants/discovery';
import * as ACCOUNT from '../actions/constants/account';
import * as CONNECT from '../actions/constants/TrezorConnect';
import type { Action, TrezorDevice } from '~/flowtype';
import type {
DiscoveryStartAction,
DiscoveryWaitingAction,
DiscoveryStopAction,
DiscoveryCompleteAction
} from '../actions/DiscoveryActions';
import type {
AccountCreateAction
} from '../actions/AccountsActions'
export type Discovery = {
network: string;
publicKey: string;
chainCode: string;
hdKey: HDKey;
basePath: Array<number>;
deviceState: string;
accountIndex: number;
interrupted: boolean;
completed: boolean;
waitingForDevice: boolean;
waitingForBackend: boolean;
}
export type State = Array<Discovery>;
const initialState: State = [];
const findIndex = (state: State, network: string, deviceState: string): number => {
return state.findIndex(d => d.network === network && d.deviceState === deviceState);
}
const start = (state: State, action: DiscoveryStartAction): State => {
const deviceState: string = action.device.state || '0';
const hdKey: HDKey = new HDKey();
hdKey.publicKey = new Buffer(action.publicKey, 'hex');
hdKey.chainCode = new Buffer(action.chainCode, 'hex');
const instance: Discovery = {
network: action.network,
publicKey: action.publicKey,
chainCode: action.chainCode,
hdKey,
basePath: action.basePath,
deviceState,
accountIndex: 0,
interrupted: false,
completed: false,
waitingForDevice: false,
waitingForBackend: false,
}
const newState: State = [ ...state ];
const index: number = findIndex(state, action.network, deviceState);
if (index >= 0) {
newState[index] = instance;
} else {
newState.push(instance);
}
return newState;
}
const complete = (state: State, action: DiscoveryCompleteAction): State => {
const index: number = findIndex(state, action.network, action.device.state || '0');
const newState: State = [ ...state ];
newState[index].completed = true;
return newState;
}
const accountCreate = (state: State, action: AccountCreateAction): State => {
const index: number = findIndex(state, action.network, action.device.state || '0');
const newState: State = [ ...state ];
newState[index].accountIndex++;
return newState;
}
const forgetDiscovery = (state: State, device: TrezorDevice): State => {
return state.filter(d => d.deviceState !== device.state);
}
const stop = (state: State, action: DiscoveryStopAction): State => {
const newState: State = [ ...state ];
return newState.map( (d: Discovery) => {
if (d.deviceState === action.device.state && !d.completed) {
d.interrupted = true;
d.waitingForDevice = false;
}
return d;
});
}
const waitingForDevice = (state: State, action: DiscoveryWaitingAction): State => {
const deviceState: string = action.device.state || '0';
const instance: Discovery = {
network: action.network,
deviceState,
publicKey: '',
chainCode: '',
hdKey: null,
basePath: [],
accountIndex: 0,
interrupted: false,
completed: false,
waitingForDevice: true,
waitingForBackend: false,
}
const index: number = findIndex(state, action.network, deviceState);
const newState: State = [ ...state ];
if (index >= 0) {
newState[index] = instance;
} else {
newState.push(instance);
}
return newState;
}
const waitingForBackend = (state: State, action: DiscoveryWaitingAction): State => {
const deviceState: string = action.device.state || '0';
const instance: Discovery = {
network: action.network,
deviceState,
publicKey: '',
chainCode: '',
hdKey: null,
basePath: [],
accountIndex: 0,
interrupted: false,
completed: false,
waitingForDevice: false,
waitingForBackend: true
}
const index: number = findIndex(state, action.network, deviceState);
const newState: State = [ ...state ];
if (index >= 0) {
newState[index] = instance;
} else {
newState.push(instance);
}
return newState;
}
export default function discovery(state: State = initialState, action: Action): State {
switch (action.type) {
case DISCOVERY.START :
return start(state, action);
case ACCOUNT.CREATE :
return accountCreate(state, action);
case DISCOVERY.STOP :
return stop(state, action);
case DISCOVERY.COMPLETE :
return complete(state, action);
case DISCOVERY.WAITING_FOR_DEVICE :
return waitingForDevice(state, action);
case DISCOVERY.WAITING_FOR_BACKEND :
return waitingForBackend(state, action);
case DISCOVERY.FROM_STORAGE :
return action.payload.map(d => {
const hdKey: HDKey = new HDKey();
hdKey.publicKey = new Buffer(d.publicKey, 'hex');
hdKey.chainCode = new Buffer(d.chainCode, 'hex');
return {
...d,
hdKey,
interrupted: false,
waitingForDevice: false,
waitingForBackend: false,
}
})
case CONNECT.FORGET :
case CONNECT.FORGET_SINGLE :
return forgetDiscovery(state, action.device);
default:
return state;
}
}