1
0
mirror of https://github.com/trezor/trezor-wallet synced 2024-11-12 11:28:56 +00:00
trezor-wallet/src/reducers/DiscoveryReducer.js

231 lines
7.3 KiB
JavaScript
Raw Normal View History

2018-02-20 09:30:36 +00:00
/* @flow */
2018-07-30 10:52:13 +00:00
2018-04-23 10:20:15 +00:00
import HDKey from 'hdkey';
2018-08-14 13:11:52 +00:00
import * as DISCOVERY from 'actions/constants/discovery';
import * as ACCOUNT from 'actions/constants/account';
import * as CONNECT from 'actions/constants/TrezorConnect';
import * as WALLET from 'actions/constants/wallet';
2018-02-20 09:30:36 +00:00
2018-08-14 12:56:47 +00:00
import type { Action, TrezorDevice } from 'flowtype';
2018-07-30 10:52:13 +00:00
import type {
2018-04-23 10:20:15 +00:00
DiscoveryStartAction,
DiscoveryWaitingAction,
2018-07-30 10:52:13 +00:00
DiscoveryCompleteAction,
2018-08-14 13:11:52 +00:00
} from 'actions/DiscoveryActions';
2018-04-23 10:20:15 +00:00
2018-09-12 11:25:32 +00:00
import type { Account } from './AccountsReducer';
2018-04-23 10:20:15 +00:00
2018-02-20 09:30:36 +00:00
export type Discovery = {
2019-03-04 12:33:02 +00:00
network: string,
basePath: Array<number>,
deviceState: string,
accountIndex: number,
interrupted: boolean,
completed: boolean,
waitingForDevice: boolean,
waitingForBlockchain: boolean,
fwNotSupported: boolean,
fwOutdated: boolean,
publicKey: string, // used in ethereum only
chainCode: string, // used in ethereum only
hdKey: HDKey, // used in ethereum only
};
2018-02-20 09:30:36 +00:00
2018-04-23 10:20:15 +00:00
export type State = Array<Discovery>;
const initialState: State = [];
const defaultDiscovery: Discovery = {
network: '',
deviceState: '',
basePath: [],
accountIndex: 0,
interrupted: false,
completed: false,
waitingForDevice: false,
waitingForBlockchain: false,
fwNotSupported: false,
fwOutdated: false,
publicKey: '',
chainCode: '',
hdKey: null,
};
2018-02-20 09:30:36 +00:00
2019-03-04 12:33:02 +00:00
const findIndex = (state: State, network: string, deviceState: string): number =>
state.findIndex(d => d.network === network && d.deviceState === deviceState);
2018-04-23 10:20:15 +00:00
const start = (state: State, action: DiscoveryStartAction): State => {
const deviceState: string = action.device.state || '0';
2018-02-20 09:30:36 +00:00
const instance: Discovery = {
...defaultDiscovery,
network: action.network.shortcut,
2018-04-23 10:20:15 +00:00
deviceState,
2018-07-30 10:52:13 +00:00
};
2018-02-20 09:30:36 +00:00
if (action.networkType === 'ethereum') {
const hdKey = new HDKey();
hdKey.publicKey = Buffer.from(action.publicKey, 'hex');
hdKey.chainCode = Buffer.from(action.chainCode, 'hex');
instance.hdKey = hdKey;
instance.publicKey = action.publicKey;
instance.chainCode = action.chainCode;
instance.basePath = action.basePath;
}
2018-07-30 10:52:13 +00:00
const newState: State = [...state];
const index: number = findIndex(state, action.network.shortcut, deviceState);
2018-02-20 09:30:36 +00:00
if (index >= 0) {
newState[index] = instance;
} else {
newState.push(instance);
}
return newState;
2018-07-30 10:52:13 +00:00
};
2018-02-20 09:30:36 +00:00
2018-04-23 10:20:15 +00:00
const complete = (state: State, action: DiscoveryCompleteAction): State => {
const index: number = findIndex(state, action.network, action.device.state || '0');
2018-07-30 10:52:13 +00:00
const newState: State = [...state];
newState[index] = { ...newState[index], completed: true };
2018-02-20 09:30:36 +00:00
return newState;
2018-07-30 10:52:13 +00:00
};
2018-02-20 09:30:36 +00:00
2018-09-12 11:25:32 +00:00
const accountCreate = (state: State, account: Account): State => {
const index: number = findIndex(state, account.network, account.deviceState);
2018-07-30 10:52:13 +00:00
const newState: State = [...state];
2019-04-08 16:30:11 +00:00
// do not increment index when adding imported account
// imported accounts should not interfere with the index used in discovery proccess.
if (!account.imported) {
newState[index].accountIndex++;
}
2018-02-20 09:30:36 +00:00
return newState;
2018-07-30 10:52:13 +00:00
};
2018-02-20 09:30:36 +00:00
2019-03-04 12:33:02 +00:00
const forgetDiscovery = (state: State, device: TrezorDevice): State =>
state.filter(d => d.deviceState !== device.state);
2018-02-20 09:30:36 +00:00
const clear = (state: State, devices: Array<TrezorDevice>): State => {
2018-07-30 10:52:13 +00:00
let newState: State = [...state];
2019-03-04 12:33:02 +00:00
devices.forEach(d => {
newState = forgetDiscovery(newState, d);
});
return newState;
2018-07-30 10:52:13 +00:00
};
2018-10-04 08:49:12 +00:00
const stop = (state: State, device: TrezorDevice): State => {
const affectedProcesses = state.filter(d => d.deviceState === device.state && !d.completed);
const otherProcesses = state.filter(d => affectedProcesses.indexOf(d) === -1);
const changedProcesses = affectedProcesses.map(d => ({
...d,
interrupted: true,
waitingForDevice: false,
waitingForBlockchain: false,
}));
return otherProcesses.concat(changedProcesses);
2018-07-30 10:52:13 +00:00
};
2018-02-20 09:30:36 +00:00
2018-05-07 11:25:46 +00:00
const waitingForDevice = (state: State, action: DiscoveryWaitingAction): State => {
2018-04-23 10:20:15 +00:00
const deviceState: string = action.device.state || '0';
2018-02-20 09:30:36 +00:00
const instance: Discovery = {
...defaultDiscovery,
network: action.network,
2018-04-23 10:20:15 +00:00
deviceState,
2018-05-07 11:25:46 +00:00
waitingForDevice: true,
2018-07-30 10:52:13 +00:00
};
2018-05-07 11:25:46 +00:00
const index: number = findIndex(state, action.network, deviceState);
2018-07-30 10:52:13 +00:00
const newState: State = [...state];
2018-05-07 11:25:46 +00:00
if (index >= 0) {
newState[index] = instance;
} else {
newState.push(instance);
}
return newState;
2018-07-30 10:52:13 +00:00
};
2018-05-07 11:25:46 +00:00
2018-09-13 12:40:41 +00:00
const waitingForBlockchain = (state: State, action: DiscoveryWaitingAction): State => {
2018-05-07 11:25:46 +00:00
const deviceState: string = action.device.state || '0';
const instance: Discovery = {
...defaultDiscovery,
2018-05-07 11:25:46 +00:00
network: action.network,
deviceState,
2018-09-13 12:40:41 +00:00
waitingForBlockchain: true,
2018-07-30 10:52:13 +00:00
};
2018-02-20 09:30:36 +00:00
2018-04-23 10:20:15 +00:00
const index: number = findIndex(state, action.network, deviceState);
2018-07-30 10:52:13 +00:00
const newState: State = [...state];
2018-02-20 09:30:36 +00:00
if (index >= 0) {
newState[index] = instance;
} else {
newState.push(instance);
}
return newState;
2018-07-30 10:52:13 +00:00
};
2018-02-20 09:30:36 +00:00
const notSupported = (state: State, action: DiscoveryWaitingAction): State => {
2019-03-04 12:33:02 +00:00
const affectedProcesses = state.filter(
d => d.deviceState === action.device.state && d.network === action.network
);
const otherProcesses = state.filter(d => affectedProcesses.indexOf(d) === -1);
const changedProcesses = affectedProcesses.map(d => ({
...d,
fwOutdated: action.type === DISCOVERY.FIRMWARE_OUTDATED,
fwNotSupported: action.type === DISCOVERY.FIRMWARE_NOT_SUPPORTED,
}));
return otherProcesses.concat(changedProcesses);
};
2018-04-23 10:20:15 +00:00
export default function discovery(state: State = initialState, action: Action): State {
2018-02-20 09:30:36 +00:00
switch (action.type) {
2018-07-30 10:52:13 +00:00
case DISCOVERY.START:
2018-02-20 09:30:36 +00:00
return start(state, action);
2018-07-30 10:52:13 +00:00
case ACCOUNT.CREATE:
2018-09-12 11:25:32 +00:00
return accountCreate(state, action.payload);
2018-07-30 10:52:13 +00:00
case DISCOVERY.STOP:
2018-10-04 08:49:12 +00:00
return stop(state, action.device);
2018-07-30 10:52:13 +00:00
case DISCOVERY.COMPLETE:
2018-02-20 09:30:36 +00:00
return complete(state, action);
2018-07-30 10:52:13 +00:00
case DISCOVERY.WAITING_FOR_DEVICE:
2018-05-07 11:25:46 +00:00
return waitingForDevice(state, action);
2018-09-13 12:40:41 +00:00
case DISCOVERY.WAITING_FOR_BLOCKCHAIN:
return waitingForBlockchain(state, action);
case DISCOVERY.FIRMWARE_NOT_SUPPORTED:
return notSupported(state, action);
case DISCOVERY.FIRMWARE_OUTDATED:
return notSupported(state, action);
2018-07-30 10:52:13 +00:00
case DISCOVERY.FROM_STORAGE:
2019-03-04 12:33:02 +00:00
return action.payload.map(d => {
if (d.publicKey.length < 1) return d;
// recreate ethereum discovery HDKey
// deprecated: will be removed after switching to blockbook
2018-07-30 10:52:13 +00:00
const hdKey: HDKey = new HDKey();
2018-10-04 08:49:12 +00:00
hdKey.publicKey = Buffer.from(d.publicKey, 'hex');
hdKey.chainCode = Buffer.from(d.chainCode, 'hex');
2018-02-20 09:30:36 +00:00
return {
...d,
hdKey,
2018-02-20 09:30:36 +00:00
interrupted: false,
2018-05-07 11:25:46 +00:00
waitingForDevice: false,
2018-09-13 12:40:41 +00:00
waitingForBlockchain: false,
2018-07-30 10:52:13 +00:00
};
});
case CONNECT.FORGET:
case CONNECT.FORGET_SINGLE:
case CONNECT.FORGET_SILENT:
case CONNECT.RECEIVE_WALLET_TYPE:
2018-04-23 10:20:15 +00:00
return forgetDiscovery(state, action.device);
2018-07-30 10:52:13 +00:00
case WALLET.CLEAR_UNAVAILABLE_DEVICE_DATA:
return clear(state, action.devices);
2018-02-20 09:30:36 +00:00
default:
return state;
}
2019-03-04 12:33:02 +00:00
}