1
0
mirror of https://github.com/trezor/trezor-wallet synced 2024-11-28 03:08:30 +00:00

Fix some eslint errors

This commit is contained in:
Vasek Mlejnsky 2018-09-05 16:17:50 +02:00
parent 1dd1ff7f0e
commit 354a16f0c0
7 changed files with 263 additions and 267 deletions

View File

@ -16,7 +16,10 @@
"regenerator": true "regenerator": true
}], }],
["module-resolver", { ["module-resolver", {
"root": ["./src"] "root": ["./src"],
"alias": {
"public": ["./public"]
}
}], }],
"babel-plugin-styled-components" "babel-plugin-styled-components"
], ],

View File

@ -4,12 +4,6 @@ import * as ACCOUNT from 'actions/constants/account';
import type { Action, TrezorDevice } from 'flowtype'; import type { Action, TrezorDevice } from 'flowtype';
import type { State } from 'reducers/AccountsReducer'; import type { State } from 'reducers/AccountsReducer';
export type AccountAction =
AccountFromStorageAction
| AccountCreateAction
| AccountSetBalanceAction
| AccountSetNonceAction;
export type AccountFromStorageAction = { export type AccountFromStorageAction = {
type: typeof ACCOUNT.FROM_STORAGE, type: typeof ACCOUNT.FROM_STORAGE,
payload: State payload: State
@ -40,6 +34,12 @@ export type AccountSetNonceAction = {
nonce: number nonce: number
} }
export type AccountAction =
AccountFromStorageAction
| AccountCreateAction
| AccountSetBalanceAction
| AccountSetNonceAction;
export const setBalance = (address: string, network: string, deviceState: string, balance: string): Action => ({ export const setBalance = (address: string, network: string, deviceState: string, balance: string): Action => ({
type: ACCOUNT.SET_BALANCE, type: ACCOUNT.SET_BALANCE,
address, address,
@ -54,4 +54,4 @@ export const setNonce = (address: string, network: string, deviceState: string,
network, network,
deviceState, deviceState,
nonce, nonce,
}); });

View File

@ -1,11 +1,9 @@
/* @flow */ /* @flow */
import TrezorConnect from 'trezor-connect'; import TrezorConnect from 'trezor-connect';
import HDKey from 'hdkey';
import EthereumjsUtil from 'ethereumjs-util'; import EthereumjsUtil from 'ethereumjs-util';
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 TOKEN from 'actions/constants/token';
import * as NOTIFICATION from 'actions/constants/notification'; import * as NOTIFICATION from 'actions/constants/notification';
import type { import type {
ThunkAction, AsyncAction, Action, GetState, Dispatch, TrezorDevice, ThunkAction, AsyncAction, Action, GetState, Dispatch, TrezorDevice,
@ -13,18 +11,9 @@ import type {
import type { Discovery, State } from 'reducers/DiscoveryReducer'; import type { Discovery, State } from 'reducers/DiscoveryReducer';
import * as AccountsActions from './AccountsActions'; import * as AccountsActions from './AccountsActions';
import { getNonceAsync, getBalanceAsync, getTokenBalanceAsync } from './Web3Actions'; import { getNonceAsync, getBalanceAsync } from './Web3Actions';
import { setBalance as setTokenBalance } from './TokenActions';
export type DiscoveryAction = {
type: typeof DISCOVERY.FROM_STORAGE,
payload: State
} | DiscoveryStartAction
| DiscoveryWaitingAction
| DiscoveryStopAction
| DiscoveryCompleteAction;
export type DiscoveryStartAction = { export type DiscoveryStartAction = {
type: typeof DISCOVERY.START, type: typeof DISCOVERY.START,
device: TrezorDevice, device: TrezorDevice,
@ -51,144 +40,29 @@ export type DiscoveryCompleteAction = {
network: string network: string
} }
export const start = (device: TrezorDevice, network: string, ignoreCompleted?: boolean): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { export type DiscoveryAction = {
const selected = getState().wallet.selectedDevice; type: typeof DISCOVERY.FROM_STORAGE,
if (!selected) { payload: State
// TODO: throw error } | DiscoveryStartAction
console.error('Start discovery: no selected device', device); | DiscoveryWaitingAction
return; | DiscoveryStopAction
} if (selected.path !== device.path) { | DiscoveryCompleteAction;
console.error('Start discovery: requested device is not selected', device, selected);
return;
} if (!selected.state) {
console.warn("Start discovery: Selected device wasn't authenticated yet...");
return;
} if (selected.connected && !selected.available) {
console.warn('Start discovery: Selected device is unavailable...');
return;
}
const web3 = getState().web3.find(w3 => w3.network === network);
if (!web3) {
console.error('Start discovery: Web3 does not exist', network);
return;
}
if (!web3.web3.currentProvider.isConnected()) {
console.error('Start discovery: Web3 is not connected', network);
dispatch({
type: DISCOVERY.WAITING_FOR_BACKEND,
device,
network,
});
return;
}
const discovery: State = getState().discovery;
const discoveryProcess: ?Discovery = discovery.find(d => d.deviceState === device.state && d.network === network);
if (!selected.connected && (!discoveryProcess || !discoveryProcess.completed)) { // Because start() is calling begin() and begin() is calling start() one of them must be declared first
dispatch({ // otherwise eslint will start complaining
type: DISCOVERY.WAITING_FOR_DEVICE, let begin;
device,
network,
});
return;
}
if (!discoveryProcess) {
dispatch(begin(device, network));
} else if (discoveryProcess.completed && !ignoreCompleted) {
dispatch({
type: DISCOVERY.COMPLETE,
device,
network,
});
} else if (discoveryProcess.interrupted || discoveryProcess.waitingForDevice) {
// discovery cycle was interrupted
// start from beginning
dispatch(begin(device, network));
} else {
dispatch(discoverAccount(device, discoveryProcess));
}
};
const begin = (device: TrezorDevice, network: string): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => {
const { config } = getState().localStorage;
const coinToDiscover = config.coins.find(c => c.network === network);
if (!coinToDiscover) return;
dispatch({
type: DISCOVERY.WAITING_FOR_DEVICE,
device,
network,
});
// get xpub from TREZOR
const response = await TrezorConnect.getPublicKey({
device: {
path: device.path,
instance: device.instance,
state: device.state,
},
path: coinToDiscover.bip44,
keepSession: true, // acquire and hold session
useEmptyPassphrase: !device.instance,
});
// handle TREZOR response error
if (!response.success) {
// TODO: check message
console.warn('DISCOVERY ERROR', response);
dispatch({
type: NOTIFICATION.ADD,
payload: {
type: 'error',
title: 'Discovery error',
message: response.payload.error,
cancelable: true,
actions: [
{
label: 'Try again',
callback: () => {
dispatch(start(device, network));
},
},
],
},
});
return;
}
// check for interruption
const discoveryProcess: ?Discovery = getState().discovery.find(d => d.deviceState === device.state && d.network === network);
if (discoveryProcess && discoveryProcess.interrupted) return;
const basePath: Array<number> = response.payload.path;
// send data to reducer
dispatch({
type: DISCOVERY.START,
network: coinToDiscover.network,
device,
publicKey: response.payload.publicKey,
chainCode: response.payload.chainCode,
basePath,
});
dispatch(start(device, network));
};
const discoverAccount = (device: TrezorDevice, discoveryProcess: Discovery): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => { const discoverAccount = (device: TrezorDevice, discoveryProcess: Discovery): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => {
const completed: boolean = discoveryProcess.completed; const { completed } = discoveryProcess;
discoveryProcess.completed = false; discoveryProcess.completed = false;
const derivedKey = discoveryProcess.hdKey.derive(`m/${discoveryProcess.accountIndex}`); const derivedKey = discoveryProcess.hdKey.derive(`m/${discoveryProcess.accountIndex}`);
const path = discoveryProcess.basePath.concat(discoveryProcess.accountIndex); const path = discoveryProcess.basePath.concat(discoveryProcess.accountIndex);
const publicAddress: string = EthereumjsUtil.publicToAddress(derivedKey.publicKey, true).toString('hex'); const publicAddress: string = EthereumjsUtil.publicToAddress(derivedKey.publicKey, true).toString('hex');
const ethAddress: string = EthereumjsUtil.toChecksumAddress(publicAddress); const ethAddress: string = EthereumjsUtil.toChecksumAddress(publicAddress);
const network = discoveryProcess.network; const { network } = discoveryProcess;
// TODO: check if address was created before // TODO: check if address was created before
@ -312,6 +186,135 @@ const discoverAccount = (device: TrezorDevice, discoveryProcess: Discovery): Asy
} }
}; };
export const start = (device: TrezorDevice, network: string, ignoreCompleted?: boolean): ThunkAction => (dispatch: Dispatch, getState: GetState): void => {
const selected = getState().wallet.selectedDevice;
if (!selected) {
// TODO: throw error
console.error('Start discovery: no selected device', device);
return;
} if (selected.path !== device.path) {
console.error('Start discovery: requested device is not selected', device, selected);
return;
} if (!selected.state) {
console.warn("Start discovery: Selected device wasn't authenticated yet...");
return;
} if (selected.connected && !selected.available) {
console.warn('Start discovery: Selected device is unavailable...');
return;
}
const web3 = getState().web3.find(w3 => w3.network === network);
if (!web3) {
console.error('Start discovery: Web3 does not exist', network);
return;
}
if (!web3.web3.currentProvider.isConnected()) {
console.error('Start discovery: Web3 is not connected', network);
dispatch({
type: DISCOVERY.WAITING_FOR_BACKEND,
device,
network,
});
return;
}
const { discovery }: { discovery: State } = getState();
const discoveryProcess: ?Discovery = discovery.find(d => d.deviceState === device.state && d.network === network);
if (!selected.connected && (!discoveryProcess || !discoveryProcess.completed)) {
dispatch({
type: DISCOVERY.WAITING_FOR_DEVICE,
device,
network,
});
return;
}
if (!discoveryProcess) {
dispatch(begin(device, network));
} else if (discoveryProcess.completed && !ignoreCompleted) {
dispatch({
type: DISCOVERY.COMPLETE,
device,
network,
});
} else if (discoveryProcess.interrupted || discoveryProcess.waitingForDevice) {
// discovery cycle was interrupted
// start from beginning
dispatch(begin(device, network));
} else {
dispatch(discoverAccount(device, discoveryProcess));
}
};
begin = (device: TrezorDevice, network: string): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => {
const { config } = getState().localStorage;
const coinToDiscover = config.coins.find(c => c.network === network);
if (!coinToDiscover) return;
dispatch({
type: DISCOVERY.WAITING_FOR_DEVICE,
device,
network,
});
// get xpub from TREZOR
const response = await TrezorConnect.getPublicKey({
device: {
path: device.path,
instance: device.instance,
state: device.state,
},
path: coinToDiscover.bip44,
keepSession: true, // acquire and hold session
useEmptyPassphrase: !device.instance,
});
// handle TREZOR response error
if (!response.success) {
// TODO: check message
console.warn('DISCOVERY ERROR', response);
dispatch({
type: NOTIFICATION.ADD,
payload: {
type: 'error',
title: 'Discovery error',
message: response.payload.error,
cancelable: true,
actions: [
{
label: 'Try again',
callback: () => {
dispatch(start(device, network));
},
},
],
},
});
return;
}
// check for interruption
const discoveryProcess: ?Discovery = getState().discovery.find(d => d.deviceState === device.state && d.network === network);
if (discoveryProcess && discoveryProcess.interrupted) return;
const basePath: Array<number> = response.payload.path;
// send data to reducer
dispatch({
type: DISCOVERY.START,
network: coinToDiscover.network,
device,
publicKey: response.payload.publicKey,
chainCode: response.payload.chainCode,
basePath,
});
dispatch(start(device, network));
};
export const restore = (): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { export const restore = (): ThunkAction => (dispatch: Dispatch, getState: GetState): void => {
const selected = getState().wallet.selectedDevice; const selected = getState().wallet.selectedDevice;

View File

@ -7,10 +7,10 @@ import * as TOKEN from 'actions/constants/token';
import * as DISCOVERY from 'actions/constants/discovery'; import * as DISCOVERY from 'actions/constants/discovery';
import * as STORAGE from 'actions/constants/localStorage'; import * as STORAGE from 'actions/constants/localStorage';
import * as PENDING from 'actions/constants/pendingTx'; import * as PENDING from 'actions/constants/pendingTx';
import { JSONRequest, httpRequest } from 'utils/networkUtils'; import { httpRequest } from 'utils/networkUtils';
import type { import type {
ThunkAction, AsyncAction, GetState, Dispatch, TrezorDevice, ThunkAction, AsyncAction, /* GetState, */ Dispatch,
} from 'flowtype'; } from 'flowtype';
import type { Config, Coin, TokensCollection } from 'reducers/LocalStorageReducer'; import type { Config, Coin, TokensCollection } from 'reducers/LocalStorageReducer';
@ -30,59 +30,66 @@ export type StorageAction = {
error: string, error: string,
}; };
export const loadData = (): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { export const get = (key: string): ?string => {
// check if local storage is available try {
// let available: boolean = true; return window.localStorage.getItem(key);
// if (typeof window.localStorage === 'undefined') { } catch (error) {
// available = false; // available = false;
// } else { return null;
// try { }
// window.localStorage.setItem('ethereum_wallet', true);
// } catch (error) {
// available = false;
// }
// }
dispatch(loadTokensFromJSON());
}; };
// const parseConfig = (json: JSON): Config => { export function update(event: StorageEvent): AsyncAction {
return async (dispatch: Dispatch/* , getState: GetState */): Promise<void> => {
if (!event.newValue) return;
// if (json['coins']) { if (event.key === 'devices') {
// check if device was added/ removed
// const newDevices: Array<TrezorDevice> = JSON.parse(event.newValue);
// const myDevices: Array<TrezorDevice> = getState().connect.devices.filter(d => d.features);
// } // if (newDevices.length !== myDevices.length) {
// const diff = myDevices.filter(d => newDevices.indexOf(d) < 0)
// console.warn("DEV LIST CHANGED!", newDevices.length, myDevices.length, diff)
// // check if difference is caused by local device which is not saved
// // or device which was saved in other tab
// }
// for (let key in json) { // const diff = oldDevices.filter(d => newDevices.indexOf())
// if (key === 'coins') { }
// } if (event.key === 'accounts') {
// } dispatch({
type: ACCOUNT.FROM_STORAGE,
payload: JSON.parse(event.newValue),
});
}
// const coins: Array<Object> = json.coins || []; if (event.key === 'tokens') {
dispatch({
type: TOKEN.FROM_STORAGE,
payload: JSON.parse(event.newValue),
});
}
// if ("coins" in json){ if (event.key === 'pending') {
// json.coins dispatch({
// } type: PENDING.FROM_STORAGE,
// if (!json.hasOwnProperty("fiatValueTickers")) throw new Error(`Property "fiatValueTickers" is missing in appConfig.json`); payload: JSON.parse(event.newValue),
// if (json.config && json.hasOwnProperty('coins') && Array.isArray(json.coins)) { });
// json.coins.map(c => { }
// return {
// } if (event.key === 'discovery') {
// }) dispatch({
// } else { type: DISCOVERY.FROM_STORAGE,
// throw new Error(`Property "coins" is missing in appConfig.json`); payload: JSON.parse(event.newValue),
// } });
}
};
// return { }
// coins: [],
// fiatValueTickers: []
// }
// }
export function loadTokensFromJSON(): AsyncAction { export function loadTokensFromJSON(): AsyncAction {
return async (dispatch: Dispatch, getState: GetState): Promise<void> => { return async (dispatch: Dispatch): Promise<void> => {
if (typeof window.localStorage === 'undefined') return; if (typeof window.localStorage === 'undefined') return;
try { try {
@ -157,57 +164,58 @@ export function loadTokensFromJSON(): AsyncAction {
}; };
} }
export function update(event: StorageEvent): AsyncAction { export const loadData = (): ThunkAction => (dispatch: Dispatch): void => {
return async (dispatch: Dispatch, getState: GetState): Promise<void> => { // check if local storage is available
if (!event.newValue) return; // let available: boolean = true;
// if (typeof window.localStorage === 'undefined') {
// available = false;
// } else {
// try {
// window.localStorage.setItem('ethereum_wallet', true);
// } catch (error) {
// available = false;
// }
// }
if (event.key === 'devices') { dispatch(loadTokensFromJSON());
// check if device was added/ removed };
// const newDevices: Array<TrezorDevice> = JSON.parse(event.newValue);
// const myDevices: Array<TrezorDevice> = getState().connect.devices.filter(d => d.features);
// if (newDevices.length !== myDevices.length) { // const parseConfig = (json: JSON): Config => {
// const diff = myDevices.filter(d => newDevices.indexOf(d) < 0)
// console.warn("DEV LIST CHANGED!", newDevices.length, myDevices.length, diff)
// // check if difference is caused by local device which is not saved
// // or device which was saved in other tab
// }
// const diff = oldDevices.filter(d => newDevices.indexOf()) // if (json['coins']) {
}
if (event.key === 'accounts') { // }
dispatch({
type: ACCOUNT.FROM_STORAGE,
payload: JSON.parse(event.newValue),
});
}
if (event.key === 'tokens') { // for (let key in json) {
dispatch({ // if (key === 'coins') {
type: TOKEN.FROM_STORAGE,
payload: JSON.parse(event.newValue),
});
}
if (event.key === 'pending') { // }
dispatch({ // }
type: PENDING.FROM_STORAGE,
payload: JSON.parse(event.newValue),
});
}
if (event.key === 'discovery') { // const coins: Array<Object> = json.coins || [];
dispatch({
type: DISCOVERY.FROM_STORAGE, // if ("coins" in json){
payload: JSON.parse(event.newValue), // json.coins
}); // }
} // if (!json.hasOwnProperty("fiatValueTickers")) throw new Error(`Property "fiatValueTickers" is missing in appConfig.json`);
}; // if (json.config && json.hasOwnProperty('coins') && Array.isArray(json.coins)) {
} // json.coins.map(c => {
// return {
// }
// })
// } else {
// throw new Error(`Property "coins" is missing in appConfig.json`);
// }
export const save = (key: string, value: string): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { // return {
// coins: [],
// fiatValueTickers: []
// }
// }
export const save = (key: string, value: string): ThunkAction => (): void => {
if (typeof window.localStorage !== 'undefined') { if (typeof window.localStorage !== 'undefined') {
try { try {
window.localStorage.setItem(key, value); window.localStorage.setItem(key, value);
@ -216,13 +224,4 @@ export const save = (key: string, value: string): ThunkAction => (dispatch: Disp
console.error(`Local Storage ERROR: ${error}`); console.error(`Local Storage ERROR: ${error}`);
} }
} }
};
export const get = (key: string): ?string => {
try {
return window.localStorage.getItem(key);
} catch (error) {
// available = false;
return null;
}
}; };

View File

@ -1,6 +1,6 @@
/* @flow */ /* @flow */
import TrezorConnect, { UI, UI_EVENT } from 'trezor-connect'; import TrezorConnect, { UI } from 'trezor-connect';
import type { Device } from 'trezor-connect'; import type { Device } from 'trezor-connect';
import * as MODAL from 'actions/constants/modal'; import * as MODAL from 'actions/constants/modal';
import * as CONNECT from 'actions/constants/TrezorConnect'; import * as CONNECT from 'actions/constants/TrezorConnect';
@ -24,14 +24,14 @@ export const onPinSubmit = (value: string): Action => {
}; };
}; };
export const onPassphraseSubmit = (passphrase: string): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => { export const onPassphraseSubmit = (/* passphrase: string */): AsyncAction => async (dispatch: Dispatch): Promise<void> => {
const resp = await TrezorConnect.uiResponse({ // const resp = await TrezorConnect.uiResponse({
type: UI.RECEIVE_PASSPHRASE, // type: UI.RECEIVE_PASSPHRASE,
payload: { // payload: {
value: passphrase, // value: passphrase,
save: true, // save: true,
}, // },
}); // });
dispatch({ dispatch({
type: MODAL.CLOSE, type: MODAL.CLOSE,
@ -64,7 +64,7 @@ export const onCancel = (): Action => ({
type: MODAL.CLOSE, type: MODAL.CLOSE,
}); });
export const onDuplicateDevice = (device: TrezorDevice): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { export const onDuplicateDevice = (device: TrezorDevice): ThunkAction => (dispatch: Dispatch): void => {
dispatch(onCancel()); dispatch(onCancel());
dispatch({ dispatch({

View File

@ -28,7 +28,7 @@ export type ReceiveAction = {
type: typeof RECEIVE.SHOW_UNVERIFIED_ADDRESS type: typeof RECEIVE.SHOW_UNVERIFIED_ADDRESS
} }
export const init = (): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { export const init = (): ThunkAction => (dispatch: Dispatch): void => {
const state: State = { const state: State = {
...initialState, ...initialState,
}; };

View File

@ -9,19 +9,13 @@ import * as PENDING from 'actions/constants/pendingTx';
import * as stateUtils from 'reducers/utils'; import * as stateUtils from 'reducers/utils';
import { initialState } from 'reducers/SelectedAccountReducer';
import type { import type {
Coin,
TrezorDevice,
AsyncAction, AsyncAction,
ThunkAction,
Action, Action,
GetState, GetState,
Dispatch, Dispatch,
State, State,
} from 'flowtype'; } from 'flowtype';
import * as SessionStorageActions from './SessionStorageActions';
import * as SendFormActions from './SendFormActions'; import * as SendFormActions from './SendFormActions';
@ -32,13 +26,14 @@ export type SelectedAccountAction = {
payload: $ElementType<State, 'selectedAccount'> payload: $ElementType<State, 'selectedAccount'>
}; };
export const dispose = (): Action => ({
type: ACCOUNT.DISPOSE,
});
export const updateSelectedValues = (prevState: State, action: Action): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => { export const updateSelectedValues = (prevState: State, action: Action): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => {
const locationChange: boolean = action.type === LOCATION_CHANGE; const locationChange: boolean = action.type === LOCATION_CHANGE;
const state: State = getState(); const state: State = getState();
const location = state.router.location; const { location } = state.router;
const prevLocation = prevState.router.location;
const needUpdate: boolean = false;
// reset form to default // reset form to default
if (action.type === SEND.TX_COMPLETE) { if (action.type === SEND.TX_COMPLETE) {
@ -126,7 +121,3 @@ export const updateSelectedValues = (prevState: State, action: Action): AsyncAct
} }
} }
}; };
export const dispose = (): Action => ({
type: ACCOUNT.DISPOSE,
});