mirror of
https://github.com/trezor/trezor-wallet
synced 2024-11-24 09:18:09 +00:00
DiscoveryAction refactoring
This commit is contained in:
parent
b4f6771544
commit
d07d078d92
@ -5,8 +5,15 @@ 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 NOTIFICATION from 'actions/constants/notification';
|
import * as NOTIFICATION from 'actions/constants/notification';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
ThunkAction, AsyncAction, PromiseAction, Action, GetState, Dispatch, TrezorDevice,
|
ThunkAction,
|
||||||
|
AsyncAction,
|
||||||
|
PromiseAction,
|
||||||
|
PayloadAction,
|
||||||
|
GetState,
|
||||||
|
Dispatch,
|
||||||
|
TrezorDevice,
|
||||||
} from 'flowtype';
|
} from 'flowtype';
|
||||||
import type { Discovery, State } from 'reducers/DiscoveryReducer';
|
import type { Discovery, State } from 'reducers/DiscoveryReducer';
|
||||||
import * as BlockchainActions from './BlockchainActions';
|
import * as BlockchainActions from './BlockchainActions';
|
||||||
@ -26,11 +33,6 @@ export type DiscoveryWaitingAction = {
|
|||||||
network: string
|
network: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DiscoveryStopAction = {
|
|
||||||
type: typeof DISCOVERY.STOP,
|
|
||||||
device: TrezorDevice
|
|
||||||
}
|
|
||||||
|
|
||||||
export type DiscoveryCompleteAction = {
|
export type DiscoveryCompleteAction = {
|
||||||
type: typeof DISCOVERY.COMPLETE,
|
type: typeof DISCOVERY.COMPLETE,
|
||||||
device: TrezorDevice,
|
device: TrezorDevice,
|
||||||
@ -40,12 +42,28 @@ export type DiscoveryCompleteAction = {
|
|||||||
export type DiscoveryAction = {
|
export type DiscoveryAction = {
|
||||||
type: typeof DISCOVERY.FROM_STORAGE,
|
type: typeof DISCOVERY.FROM_STORAGE,
|
||||||
payload: State
|
payload: State
|
||||||
|
} | {
|
||||||
|
type: typeof DISCOVERY.STOP,
|
||||||
|
device: TrezorDevice
|
||||||
} | DiscoveryStartAction
|
} | DiscoveryStartAction
|
||||||
| DiscoveryWaitingAction
|
| DiscoveryWaitingAction
|
||||||
| DiscoveryStopAction
|
|
||||||
| DiscoveryCompleteAction;
|
| DiscoveryCompleteAction;
|
||||||
|
|
||||||
export const start = (device: TrezorDevice, network: string, ignoreCompleted?: boolean): ThunkAction => (dispatch: Dispatch, getState: GetState): void => {
|
// There are multiple async methods during discovery process (trezor-connect and blockchain actions)
|
||||||
|
// This method will check after each of async action if process was interrupted (for example by network change or device disconnect)
|
||||||
|
const isProcessInterrupted = (process?: Discovery): PayloadAction<boolean> => (dispatch: Dispatch, getState: GetState): boolean => {
|
||||||
|
if (!process) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const { deviceState, network } = process;
|
||||||
|
const discoveryProcess: ?Discovery = getState().discovery.find(d => d.deviceState === deviceState && d.network === network);
|
||||||
|
if (!discoveryProcess) return false;
|
||||||
|
return discoveryProcess.interrupted;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Private action
|
||||||
|
// Called from "this.begin", "this.restore", "this.addAccount"
|
||||||
|
const start = (device: TrezorDevice, network: string, ignoreCompleted?: boolean): ThunkAction => (dispatch: Dispatch, getState: GetState): void => {
|
||||||
const selected = getState().wallet.selectedDevice;
|
const selected = getState().wallet.selectedDevice;
|
||||||
if (!selected) {
|
if (!selected) {
|
||||||
// TODO: throw error
|
// TODO: throw error
|
||||||
@ -150,8 +168,10 @@ const begin = (device: TrezorDevice, network: string): AsyncAction => async (dis
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check for interruption
|
// check for interruption
|
||||||
const discoveryProcess: ?Discovery = getState().discovery.find(d => d.deviceState === device.state && d.network === network);
|
// corner case: DISCOVERY.START wasn't called yet, but Discovery exists in reducer created by DISCOVERY.WAITING_FOR_DEVICE action
|
||||||
if (discoveryProcess && discoveryProcess.interrupted) return;
|
// this is why we need to get process instance directly from reducer
|
||||||
|
const discoveryProcess = getState().discovery.find(d => d.deviceState === device.state && d.network === network);
|
||||||
|
if (dispatch(isProcessInterrupted(discoveryProcess))) return;
|
||||||
|
|
||||||
const basePath: Array<number> = response.payload.path;
|
const basePath: Array<number> = response.payload.path;
|
||||||
|
|
||||||
@ -181,7 +201,8 @@ const discoverAccount = (device: TrezorDevice, discoveryProcess: Discovery): Asy
|
|||||||
// TODO: check if address was created before
|
// TODO: check if address was created before
|
||||||
try {
|
try {
|
||||||
const account = await dispatch(BlockchainActions.discoverAccount(device, ethAddress, network));
|
const account = await dispatch(BlockchainActions.discoverAccount(device, ethAddress, network));
|
||||||
if (discoveryProcess.interrupted) return;
|
// check for interruption
|
||||||
|
if (dispatch(isProcessInterrupted(discoveryProcess))) return;
|
||||||
|
|
||||||
// const accountIsEmpty = account.transactions <= 0 && account.nonce <= 0 && account.balance === '0';
|
// const accountIsEmpty = account.transactions <= 0 && account.nonce <= 0 && account.balance === '0';
|
||||||
const accountIsEmpty = account.nonce <= 0 && account.balance === '0';
|
const accountIsEmpty = account.nonce <= 0 && account.balance === '0';
|
||||||
@ -248,7 +269,7 @@ const finish = (device: TrezorDevice, discoveryProcess: Discovery): AsyncAction
|
|||||||
|
|
||||||
await dispatch(BlockchainActions.subscribe(discoveryProcess.network));
|
await dispatch(BlockchainActions.subscribe(discoveryProcess.network));
|
||||||
|
|
||||||
if (discoveryProcess.interrupted) return;
|
if (dispatch(isProcessInterrupted(discoveryProcess))) return;
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: DISCOVERY.COMPLETE,
|
type: DISCOVERY.COMPLETE,
|
||||||
@ -262,34 +283,43 @@ export const reconnect = (network: string): PromiseAction<void> => async (dispat
|
|||||||
dispatch(restore());
|
dispatch(restore());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Called after DEVICE.CONNECT ('trezor-connect') or CONNECT.AUTH_DEVICE actions in WalletService
|
||||||
|
// OR after BlockchainSubscribe in this.reconnect
|
||||||
export const restore = (): ThunkAction => (dispatch: Dispatch, getState: GetState): void => {
|
export const restore = (): ThunkAction => (dispatch: Dispatch, getState: GetState): void => {
|
||||||
const selected = getState().wallet.selectedDevice;
|
// check if current url has "network" parameter
|
||||||
if (selected && selected.connected && selected.features) {
|
const urlParams = getState().router.location.state;
|
||||||
const discoveryProcess: ?Discovery = getState().discovery.find(d => d.deviceState === selected.state && (d.interrupted || d.waitingForDevice || d.waitingForBlockchain));
|
if (!urlParams.network) return;
|
||||||
if (discoveryProcess) {
|
|
||||||
dispatch(start(selected, discoveryProcess.network));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: rename method to something intuitive
|
// make sure that "selectedDevice" exists
|
||||||
// there is no discovery process but it should be
|
|
||||||
// this is possible race condition when "network" was changed in url but device was not authenticated yet
|
|
||||||
// try to start discovery after CONNECT.AUTH_DEVICE action
|
|
||||||
export const check = (): ThunkAction => (dispatch: Dispatch, getState: GetState): void => {
|
|
||||||
const selected = getState().wallet.selectedDevice;
|
const selected = getState().wallet.selectedDevice;
|
||||||
if (!selected) return;
|
if (!selected) return;
|
||||||
|
|
||||||
const urlParams = getState().router.location.state;
|
// find discovery process for requested network
|
||||||
if (urlParams.network) {
|
const discoveryProcess: ?Discovery = getState().discovery.find(d => d.deviceState === selected.state && d.network === urlParams.network);
|
||||||
const discoveryProcess: ?Discovery = getState().discovery.find(d => d.deviceState === selected.state && d.network === urlParams.network);
|
|
||||||
if (!discoveryProcess) {
|
// if there was no process befor OR process was interrupted/waiting
|
||||||
dispatch(start(selected, urlParams.network));
|
const shouldStart = !discoveryProcess || (discoveryProcess.interrupted || discoveryProcess.waitingForDevice || discoveryProcess.waitingForBlockchain);
|
||||||
}
|
if (shouldStart) {
|
||||||
|
dispatch(start(selected, urlParams.network));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const stop = (device: TrezorDevice): Action => ({
|
export const stop = (): ThunkAction => (dispatch: Dispatch, getState: GetState): void => {
|
||||||
type: DISCOVERY.STOP,
|
const device: ?TrezorDevice = getState().wallet.selectedDevice;
|
||||||
device,
|
if (!device) return;
|
||||||
});
|
|
||||||
|
// get all uncompleted discovery processes which assigned to selected device
|
||||||
|
const discoveryProcesses = getState().discovery.filter(d => d.deviceState === device.state && !d.completed);
|
||||||
|
if (discoveryProcesses.length > 0) {
|
||||||
|
dispatch({
|
||||||
|
type: DISCOVERY.STOP,
|
||||||
|
device,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const addAccount = (): ThunkAction => (dispatch: Dispatch, getState: GetState): void => {
|
||||||
|
const selected = getState().wallet.selectedDevice;
|
||||||
|
if (!selected) return;
|
||||||
|
dispatch(start(selected, getState().router.location.state.network, true));
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user