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-06 17:04:28 +02:00
parent f5ddddc1fb
commit 58823e3a81
49 changed files with 354 additions and 422 deletions

View File

@ -5,37 +5,29 @@ import EthereumjsUtil from 'ethereumjs-util';
import EthereumjsUnits from 'ethereumjs-units'; import EthereumjsUnits from 'ethereumjs-units';
import EthereumjsTx from 'ethereumjs-tx'; import EthereumjsTx from 'ethereumjs-tx';
import TrezorConnect from 'trezor-connect'; import TrezorConnect from 'trezor-connect';
import { push } from 'react-router-redux';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import { strip } from 'utils/ethUtils';
import * as NOTIFICATION from 'actions/constants/notification'; import * as NOTIFICATION from 'actions/constants/notification';
import * as SEND from 'actions/constants/send'; import * as SEND from 'actions/constants/send';
import { initialState } from 'reducers/SendFormReducer'; import { initialState } from 'reducers/SendFormReducer';
import { findAccount } from 'reducers/AccountsReducer';
import { findToken } from 'reducers/TokensReducer'; import { findToken } from 'reducers/TokensReducer';
import { findDevice } from 'reducers/utils'; import { findDevice, getPendingAmount, getPendingNonce } from 'reducers/utils';
import * as stateUtils from 'reducers/utils';
import type { import type {
PendingTx,
Dispatch, Dispatch,
GetState, GetState,
Action, Action,
ThunkAction, ThunkAction,
AsyncAction, AsyncAction,
RouterLocationState,
TrezorDevice, TrezorDevice,
} from 'flowtype'; } from 'flowtype';
import type { State as AccountState } from 'reducers/SelectedAccountReducer'; import type { Coin } from 'reducers/LocalStorageReducer';
import type { Web3Instance } from 'reducers/Web3Reducer';
import type { Config, Coin } from 'reducers/LocalStorageReducer';
import type { Token } from 'reducers/TokensReducer'; import type { Token } from 'reducers/TokensReducer';
import type { State, FeeLevel } from 'reducers/SendFormReducer'; import type { State, FeeLevel } from 'reducers/SendFormReducer';
import type { Account } from 'reducers/AccountsReducer'; import type { Account } from 'reducers/AccountsReducer';
import type { Props } from 'views/Wallet/views/AccountSend/Container'; import type { Props } from 'views/Wallet/views/AccountSend/Container';
import * as SessionStorageActions from './SessionStorageActions'; import * as SessionStorageActions from './SessionStorageActions';
import { estimateGas, getGasPrice, pushTx } from './Web3Actions'; import { estimateGas, pushTx } from './Web3Actions';
export type SendTxAction = { export type SendTxAction = {
type: typeof SEND.TX_COMPLETE, type: typeof SEND.TX_COMPLETE,
@ -155,7 +147,6 @@ export const calculate = (prevProps: Props, props: Props) => {
} = props.selectedAccount; } = props.selectedAccount;
if (!account) return; if (!account) return;
const prevState = prevProps.sendForm;
const state = props.sendForm; const state = props.sendForm;
const isToken: boolean = state.currency !== state.networkSymbol; const isToken: boolean = state.currency !== state.networkSymbol;
@ -169,7 +160,7 @@ export const calculate = (prevProps: Props, props: Props) => {
if (state.setMax) { if (state.setMax) {
const pendingAmount: BigNumber = stateUtils.getPendingAmount(pending, state.currency, isToken); const pendingAmount: BigNumber = getPendingAmount(pending, state.currency, isToken);
if (isToken) { if (isToken) {
const token: ?Token = findToken(tokens, account.address, state.currency, account.deviceState); const token: ?Token = findToken(tokens, account.address, state.currency, account.deviceState);
@ -277,7 +268,7 @@ export const init = (): ThunkAction => (dispatch: Dispatch, getState: GetState):
}); });
}; };
export const toggleAdvanced = (address: string): Action => ({ export const toggleAdvanced = (/* address: string */): Action => ({
type: SEND.TOGGLE_ADVANCED, type: SEND.TOGGLE_ADVANCED,
}); });
@ -286,7 +277,6 @@ const addressValidation = (): ThunkAction => (dispatch: Dispatch, getState: GetS
const { const {
account, account,
network, network,
tokens,
} = getState().selectedAccount; } = getState().selectedAccount;
if (!account || !network) return; if (!account || !network) return;
@ -310,7 +300,7 @@ const addressValidation = (): ThunkAction => (dispatch: Dispatch, getState: GetS
} else { } else {
const otherNetworkAccount = savedAccounts[0]; const otherNetworkAccount = savedAccounts[0];
const device: ?TrezorDevice = findDevice(getState().devices, otherNetworkAccount.deviceID, otherNetworkAccount.deviceState); const device: ?TrezorDevice = findDevice(getState().devices, otherNetworkAccount.deviceID, otherNetworkAccount.deviceState);
const coins = getState().localStorage.config.coins; const { coins } = getState().localStorage.config;
const otherNetwork: ?Coin = coins.find(c => c.network === otherNetworkAccount.network); const otherNetwork: ?Coin = coins.find(c => c.network === otherNetworkAccount.network);
if (device && otherNetwork) { if (device && otherNetwork) {
warnings.address = `Looks like it's ${device.instanceLabel} Account #${(otherNetworkAccount.index + 1)} address of ${otherNetwork.name} network`; warnings.address = `Looks like it's ${device.instanceLabel} Account #${(otherNetworkAccount.index + 1)} address of ${otherNetwork.name} network`;
@ -351,7 +341,7 @@ export const validation = (props: Props): void => {
if (state.untouched) return; if (state.untouched) return;
// valid address // valid address
if (state.touched.address) { if (state.touched.address) {
if (state.address.length < 1) { /* if (state.address.length < 1) {
errors.address = 'Address is not set'; errors.address = 'Address is not set';
} else if (!EthereumjsUtil.isValidAddress(state.address)) { } else if (!EthereumjsUtil.isValidAddress(state.address)) {
errors.address = 'Address is not valid'; errors.address = 'Address is not valid';
@ -363,6 +353,20 @@ export const validation = (props: Props): void => {
} else if (state.infos.address) { } else if (state.infos.address) {
infos.address = state.infos.address; infos.address = state.infos.address;
} }
} */
/* eslint (no-lonely-if) */
if (state.address.length < 1) {
errors.address = 'Address is not set';
} else if (!EthereumjsUtil.isValidAddress(state.address)) {
errors.address = 'Address is not valid';
} else if (state.warnings.address) {
// address warning or info are set in addressValidation ThunkAction
// do not override this
warnings.address = state.warnings.address;
if (state.infos.address) {
infos.address = state.infos.address;
}
} }
} }
@ -376,7 +380,7 @@ export const validation = (props: Props): void => {
errors.amount = 'Amount is not a number'; errors.amount = 'Amount is not a number';
} else { } else {
let decimalRegExp: RegExp; let decimalRegExp: RegExp;
const pendingAmount: BigNumber = stateUtils.getPendingAmount(pending, state.currency, state.currency !== state.networkSymbol); const pendingAmount: BigNumber = getPendingAmount(pending, state.currency, state.currency !== state.networkSymbol);
if (state.currency !== state.networkSymbol) { if (state.currency !== state.networkSymbol) {
const token = findToken(tokens, account.address, state.currency, account.deviceState); const token = findToken(tokens, account.address, state.currency, account.deviceState);
@ -612,7 +616,7 @@ export const updateFeeLevels = (): ThunkAction => (dispatch: Dispatch, getState:
// update only gasPrice // update only gasPrice
currentState.selectedFeeLevel.gasPrice = currentState.recommendedGasPrice; currentState.selectedFeeLevel.gasPrice = currentState.recommendedGasPrice;
// leave gas limit as it was // leave gas limit as it was
gasLimit = currentState.gasLimit; ({ gasLimit } = currentState);
} }
const feeLevels: Array<FeeLevel> = getFeeLevels(network.symbol, currentState.recommendedGasPrice, gasLimit, currentState.selectedFeeLevel); const feeLevels: Array<FeeLevel> = getFeeLevels(network.symbol, currentState.recommendedGasPrice, gasLimit, currentState.selectedFeeLevel);
@ -659,9 +663,8 @@ export const onGasPriceChange = (gasPrice: string): ThunkAction => (dispatch: Di
}); });
}; };
export const onGasLimitChange = (gasLimit: string, updateFeeLevels: boolean = false): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { export const onGasLimitChange = (gasLimit: string/* , shouldUpdateFeeLevels: boolean = false */): ThunkAction => (dispatch: Dispatch, getState: GetState): void => {
const currentState: State = getState().sendForm; const currentState: State = getState().sendForm;
const isToken: boolean = currentState.currency !== currentState.networkSymbol;
const touched = { ...currentState.touched }; const touched = { ...currentState.touched };
touched.gasLimit = true; touched.gasLimit = true;
@ -704,34 +707,6 @@ export const onNonceChange = (nonce: string): AsyncAction => async (dispatch: Di
}); });
}; };
export const onDataChange = (data: string): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => {
const currentState: State = getState().sendForm;
const touched = { ...currentState.touched };
touched.data = true;
const state: State = {
...currentState,
calculatingGasLimit: true,
untouched: false,
touched,
data,
};
if (currentState.selectedFeeLevel.value !== 'Custom') {
const customLevel = currentState.feeLevels.find(f => f.value === 'Custom');
if (!customLevel) return;
state.selectedFeeLevel = customLevel;
}
dispatch({
type: SEND.DATA_CHANGE,
state,
});
dispatch(estimateGasPrice());
};
const estimateGasPrice = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => { const estimateGasPrice = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => {
const { const {
web3, web3,
@ -771,6 +746,33 @@ const estimateGasPrice = (): AsyncAction => async (dispatch: Dispatch, getState:
} }
}; };
export const onDataChange = (data: string): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => {
const currentState: State = getState().sendForm;
const touched = { ...currentState.touched };
touched.data = true;
const state: State = {
...currentState,
calculatingGasLimit: true,
untouched: false,
touched,
data,
};
if (currentState.selectedFeeLevel.value !== 'Custom') {
const customLevel = currentState.feeLevels.find(f => f.value === 'Custom');
if (!customLevel) return;
state.selectedFeeLevel = customLevel;
}
dispatch({
type: SEND.DATA_CHANGE,
state,
});
dispatch(estimateGasPrice());
};
export const onSend = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => { export const onSend = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => {
const { const {
account, account,
@ -806,7 +808,7 @@ export const onSend = (): AsyncAction => async (dispatch: Dispatch, getState: Ge
txAddress = token.address; txAddress = token.address;
} }
const pendingNonce: number = stateUtils.getPendingNonce(pending); const pendingNonce: number = getPendingNonce(pending);
const nonce = pendingNonce > 0 && pendingNonce >= account.nonce ? pendingNonce : account.nonce; const nonce = pendingNonce > 0 && pendingNonce >= account.nonce ? pendingNonce : account.nonce;
console.warn('NONCE', nonce, account.nonce, pendingNonce); console.warn('NONCE', nonce, account.nonce, pendingNonce);

View File

@ -1,17 +1,11 @@
/* @flow */ /* @flow */
import EthereumjsUtil from 'ethereumjs-util';
import * as SUMMARY from 'actions/constants/summary'; import * as SUMMARY from 'actions/constants/summary';
import * as TOKEN from 'actions/constants/token';
import { resolveAfter } from 'utils/promiseUtils';
import { initialState } from 'reducers/SummaryReducer'; import { initialState } from 'reducers/SummaryReducer';
import type { import type {
ThunkAction, AsyncAction, Action, GetState, Dispatch, ThunkAction, Action, Dispatch,
} from 'flowtype'; } from 'flowtype';
import type { State } from 'reducers/SummaryReducer'; import type { State } from 'reducers/SummaryReducer';
import type { Token } from 'reducers/TokensReducer';
export type SummaryAction = { export type SummaryAction = {
type: typeof SUMMARY.INIT, type: typeof SUMMARY.INIT,
@ -22,7 +16,7 @@ export type SummaryAction = {
type: typeof SUMMARY.DETAILS_TOGGLE type: typeof SUMMARY.DETAILS_TOGGLE
} }
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

@ -25,10 +25,6 @@ export type TokenAction = {
payload: State payload: State
} }
type SelectOptions = {
options?: Array<NetworkToken>
}
// action from component <reactSelect> // action from component <reactSelect>
export const load = (input: string, network: string): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<any> => { export const load = (input: string, network: string): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<any> => {
@ -57,6 +53,20 @@ export const load = (input: string, network: string): AsyncAction => async (disp
//await resolveAfter(3000); //await resolveAfter(3000);
}; };
export const setBalance = (tokenAddress: string, ethAddress: string, balance: string): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => {
const newState: Array<Token> = [...getState().tokens];
const token: ?Token = newState.find(t => t.address === tokenAddress && t.ethAddress === ethAddress);
if (token) {
token.loaded = true;
token.balance = balance;
}
dispatch({
type: TOKEN.SET_BALANCE,
payload: newState,
});
};
export const add = (token: NetworkToken, account: Account): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => { export const add = (token: NetworkToken, account: Account): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => {
const web3instance = getState().web3.find(w3 => w3.network === account.network); const web3instance = getState().web3.find(w3 => w3.network === account.network);
if (!web3instance) return; if (!web3instance) return;
@ -82,20 +92,6 @@ export const add = (token: NetworkToken, account: Account): AsyncAction => async
dispatch(setBalance(token.address, account.address, tokenBalance)); dispatch(setBalance(token.address, account.address, tokenBalance));
}; };
export const setBalance = (tokenAddress: string, ethAddress: string, balance: string): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => {
const newState: Array<Token> = [...getState().tokens];
const token: ?Token = newState.find(t => t.address === tokenAddress && t.ethAddress === ethAddress);
if (token) {
token.loaded = true;
token.balance = balance;
}
dispatch({
type: TOKEN.SET_BALANCE,
payload: newState,
});
};
export const remove = (token: Token): Action => ({ export const remove = (token: Token): Action => ({
type: TOKEN.REMOVE, type: TOKEN.REMOVE,
token, token,

View File

@ -1,10 +1,7 @@
/* @flow */ /* @flow */
import TrezorConnect, { import TrezorConnect, {
UI, DEVICE, DEVICE_EVENT, UI_EVENT, TRANSPORT_EVENT, DEVICE, DEVICE_EVENT, UI_EVENT, TRANSPORT_EVENT,
} from 'trezor-connect'; } from 'trezor-connect';
import * as TOKEN from 'actions/constants/token';
import * as CONNECT from 'actions/constants/TrezorConnect'; import * as CONNECT from 'actions/constants/TrezorConnect';
import * as NOTIFICATION from 'actions/constants/notification'; import * as NOTIFICATION from 'actions/constants/notification';
import * as WALLET from 'actions/constants/wallet'; import * as WALLET from 'actions/constants/wallet';
@ -82,6 +79,13 @@ export type TrezorConnectAction = {
}; };
const sortDevices = (devices: Array<TrezorDevice>): Array<TrezorDevice> => devices.sort((a, b) => {
if (!a.ts || !b.ts) {
return -1;
}
return a.ts > b.ts ? -1 : 1;
});
export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => { export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => {
// set listeners // set listeners
TrezorConnect.on(DEVICE_EVENT, (event: DeviceMessage): void => { TrezorConnect.on(DEVICE_EVENT, (event: DeviceMessage): void => {
@ -112,7 +116,7 @@ export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetS
}); });
// $FlowIssue LOCAL not declared // $FlowIssue LOCAL not declared
window.__TREZOR_CONNECT_SRC = typeof LOCAL === 'string' ? LOCAL : 'https://sisyfos.trezor.io/connect/'; // window.__TREZOR_CONNECT_SRC = typeof LOCAL === 'string' ? LOCAL : 'https://sisyfos.trezor.io/connect/';
// window.__TREZOR_CONNECT_SRC = typeof LOCAL === 'string' ? LOCAL : 'https://connect.trezor.io/5/'; // window.__TREZOR_CONNECT_SRC = typeof LOCAL === 'string' ? LOCAL : 'https://connect.trezor.io/5/';
//window.__TREZOR_CONNECT_SRC = 'https://sisyfos.trezor.io/connect/'; //window.__TREZOR_CONNECT_SRC = 'https://sisyfos.trezor.io/connect/';
// window.__TREZOR_CONNECT_SRC = 'https://localhost:8088/'; // window.__TREZOR_CONNECT_SRC = 'https://localhost:8088/';
@ -133,71 +137,6 @@ export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetS
} }
}; };
// called after backend was initialized
// set listeners for connect/disconnect
export const postInit = (): ThunkAction => (dispatch: Dispatch, getState: GetState): void => {
const handleDeviceConnect = (device: Device) => {
dispatch(initConnectedDevice(device));
};
TrezorConnect.off(DEVICE.CONNECT, handleDeviceConnect);
TrezorConnect.off(DEVICE.CONNECT_UNACQUIRED, handleDeviceConnect);
TrezorConnect.on(DEVICE.CONNECT, handleDeviceConnect);
TrezorConnect.on(DEVICE.CONNECT_UNACQUIRED, handleDeviceConnect);
const { devices } = getState();
const { initialPathname, initialParams } = getState().wallet;
if (initialPathname) {
dispatch({
type: WALLET.SET_INITIAL_URL,
// pathname: null,
// params: null
});
}
if (devices.length > 0) {
const unacquired: ?TrezorDevice = devices.find(d => d.features);
if (unacquired) {
dispatch(onSelectDevice(unacquired));
} else {
const latest: Array<TrezorDevice> = sortDevices(devices);
const firstConnected: ?TrezorDevice = latest.find(d => d.connected);
dispatch(onSelectDevice(firstConnected || latest[0]));
// TODO
if (initialParams) {
if (!initialParams.hasOwnProperty('network') && initialPathname !== getState().router.location.pathname) {
// dispatch( push(initialPathname) );
} else {
}
}
}
}
};
const sortDevices = (devices: Array<TrezorDevice>): Array<TrezorDevice> => devices.sort((a, b) => {
if (!a.ts || !b.ts) {
return -1;
}
return a.ts > b.ts ? -1 : 1;
});
export const initConnectedDevice = (device: TrezorDevice | Device): ThunkAction => (dispatch: Dispatch, getState: GetState): void => {
const selected = getState().wallet.selectedDevice;
// if (!selected || (selected && selected.state)) {
dispatch(onSelectDevice(device));
// }
// if (device.unacquired && selected && selected.path !== device.path && !selected.connected) {
// dispatch( onSelectDevice(device) );
// } else if (!selected) {
// dispatch( onSelectDevice(device) );
// }
};
// selection from Aside dropdown button // selection from Aside dropdown button
// after device_connect event // after device_connect event
// or after acquiring device // or after acquiring device
@ -242,6 +181,62 @@ export const onSelectDevice = (device: TrezorDevice | Device): ThunkAction => (d
} }
}; };
export const initConnectedDevice = (device: TrezorDevice | Device): ThunkAction => (dispatch: Dispatch/* , getState: GetState */): void => {
// const selected = getState().wallet.selectedDevice;
// if (!selected || (selected && selected.state)) {
dispatch(onSelectDevice(device));
// }
// if (device.unacquired && selected && selected.path !== device.path && !selected.connected) {
// dispatch( onSelectDevice(device) );
// } else if (!selected) {
// dispatch( onSelectDevice(device) );
// }
};
// called after backend was initialized
// set listeners for connect/disconnect
export const postInit = (): ThunkAction => (dispatch: Dispatch, getState: GetState): void => {
const handleDeviceConnect = (device: Device) => {
dispatch(initConnectedDevice(device));
};
TrezorConnect.off(DEVICE.CONNECT, handleDeviceConnect);
TrezorConnect.off(DEVICE.CONNECT_UNACQUIRED, handleDeviceConnect);
TrezorConnect.on(DEVICE.CONNECT, handleDeviceConnect);
TrezorConnect.on(DEVICE.CONNECT_UNACQUIRED, handleDeviceConnect);
const { devices } = getState();
const { initialPathname, initialParams } = getState().wallet;
if (initialPathname) {
dispatch({
type: WALLET.SET_INITIAL_URL,
// pathname: null,
// params: null
});
}
if (devices.length > 0) {
const unacquired: ?TrezorDevice = devices.find(d => d.features);
if (unacquired) {
dispatch(onSelectDevice(unacquired));
} else {
const latest: Array<TrezorDevice> = sortDevices(devices);
const firstConnected: ?TrezorDevice = latest.find(d => d.connected);
dispatch(onSelectDevice(firstConnected || latest[0]));
// TODO
if (initialParams) {
if (!initialParams.hasOwnProperty('network') && initialPathname !== getState().router.location.pathname) {
// dispatch( push(initialPathname) );
}
}
}
}
};
export const switchToFirstAvailableDevice = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => { export const switchToFirstAvailableDevice = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => {
const { devices } = getState(); const { devices } = getState();
if (devices.length > 0) { if (devices.length > 0) {
@ -388,7 +383,7 @@ export function acquire(): AsyncAction {
}; };
} }
export const gotoDeviceSettings = (device: TrezorDevice): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { export const gotoDeviceSettings = (device: TrezorDevice): ThunkAction => (dispatch: Dispatch): void => {
if (device.features) { if (device.features) {
const devUrl: string = `${device.features.device_id}${device.instance ? `:${device.instance}` : ''}`; const devUrl: string = `${device.features.device_id}${device.instance ? `:${device.instance}` : ''}`;
dispatch(push(`/device/${devUrl}/settings`)); dispatch(push(`/device/${devUrl}/settings`));

View File

@ -3,16 +3,10 @@
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 CONNECT from 'actions/constants/TrezorConnect';
import * as stateUtils from 'reducers/utils'; import * as stateUtils from 'reducers/utils';
import type import type
{ {
Account,
Coin,
Discovery,
Token,
Web3Instance,
Device, Device,
TrezorDevice, TrezorDevice,
RouterLocationState, RouterLocationState,
@ -47,8 +41,8 @@ export type WalletAction = {
devices: Array<TrezorDevice> devices: Array<TrezorDevice>
} }
export const init = (): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { export const init = (): ThunkAction => (dispatch: Dispatch): void => {
const updateOnlineStatus = (event) => { const updateOnlineStatus = () => {
dispatch({ dispatch({
type: WALLET.ONLINE_STATUS, type: WALLET.ONLINE_STATUS,
online: navigator.onLine, online: navigator.onLine,
@ -72,7 +66,7 @@ export const toggleDeviceDropdown = (opened: boolean): WalletAction => ({
// all saved instances will be removed immediately inside DevicesReducer // all saved instances will be removed immediately inside DevicesReducer
// This method will clear leftovers associated with removed instances from reducers. // This method will clear leftovers associated with removed instances from reducers.
// (DiscoveryReducer, AccountReducer, TokensReducer) // (DiscoveryReducer, AccountReducer, TokensReducer)
export const clearUnavailableDevicesData = (prevState: State, device: Device): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { export const clearUnavailableDevicesData = (prevState: State, device: Device): ThunkAction => (dispatch: Dispatch): void => {
if (!device.features) return; if (!device.features) return;
const affectedDevices = prevState.devices.filter(d => d.features && device.features const affectedDevices = prevState.devices.filter(d => d.features && device.features

View File

@ -1,23 +1,19 @@
/* @flow */ /* @flow */
import Web3 from 'web3'; import Web3 from 'web3';
import HDKey from 'hdkey';
import EthereumjsUtil from 'ethereumjs-util'; import type {
import EthereumjsTx from 'ethereumjs-tx'; ContractFactory,
import TrezorConnect from 'trezor-connect'; EstimateGasOptions,
import type { ContractFactory, EstimateGasOptions } from 'web3'; TransactionStatus,
TransactionReceipt,
} from 'web3';
import type BigNumber from 'bignumber.js'; import type BigNumber from 'bignumber.js';
import type { TransactionStatus, TransactionReceipt } from 'web3';
import { strip } from 'utils/ethUtils';
import * as WEB3 from 'actions/constants/web3'; import * as WEB3 from 'actions/constants/web3';
import * as PENDING from 'actions/constants/pendingTx'; import * as PENDING from 'actions/constants/pendingTx';
import type { import type {
Dispatch, Dispatch,
GetState, GetState,
Action,
AsyncAction, AsyncAction,
} from 'flowtype'; } from 'flowtype';
@ -29,15 +25,6 @@ import type { NetworkToken } from 'reducers/LocalStorageReducer';
import * as TokenActions from './TokenActions'; import * as TokenActions from './TokenActions';
import * as AccountsActions from './AccountsActions'; import * as AccountsActions from './AccountsActions';
export type Web3Action = {
type: typeof WEB3.READY,
} | {
type: typeof WEB3.CREATE,
instance: Web3Instance
}
| Web3UpdateBlockAction
| Web3UpdateGasPriceAction;
export type Web3UpdateBlockAction = { export type Web3UpdateBlockAction = {
type: typeof WEB3.BLOCK_UPDATED, type: typeof WEB3.BLOCK_UPDATED,
network: string, network: string,
@ -50,6 +37,14 @@ export type Web3UpdateGasPriceAction = {
gasPrice: string gasPrice: string
}; };
export type Web3Action = {
type: typeof WEB3.READY,
} | {
type: typeof WEB3.CREATE,
instance: Web3Instance
}
| Web3UpdateBlockAction
| Web3UpdateGasPriceAction;
export function init(instance: ?Web3, coinIndex: number = 0): AsyncAction { export function init(instance: ?Web3, coinIndex: number = 0): AsyncAction {
return async (dispatch: Dispatch, getState: GetState): Promise<void> => { return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
@ -64,7 +59,7 @@ export function init(instance: ?Web3, coinIndex: number = 0): AsyncAction {
return; return;
} }
const network = coin.network; const { network } = coin;
const urls = coin.backends[0].urls; const urls = coin.backends[0].urls;
let web3host: string = urls[0]; let web3host: string = urls[0];
@ -150,7 +145,7 @@ export function init(instance: ?Web3, coinIndex: number = 0): AsyncAction {
//const shh = instance.shh.newIdentity(); //const shh = instance.shh.newIdentity();
const latestBlockFilter = web3.eth.filter('latest'); // const latestBlockFilter = web3.eth.filter('latest');
const onBlockMined = async (error: ?Error, blockHash: ?string) => { const onBlockMined = async (error: ?Error, blockHash: ?string) => {
if (error) { if (error) {
@ -186,16 +181,12 @@ export function init(instance: ?Web3, coinIndex: number = 0): AsyncAction {
} }
const tokens = getState().tokens.filter(t => t.network === network); const tokens = getState().tokens.filter(t => t.network === network);
for (const token of tokens) { tokens.forEach(token => dispatch(getTokenBalance(token)));
dispatch(getTokenBalance(token));
}
dispatch(getGasPrice(network)); dispatch(getGasPrice(network));
const pending = getState().pending.filter(p => p.network === network); const pending = getState().pending.filter(p => p.network === network);
for (const tx of pending) { pending.forEach(pendingTx => dispatch(getTransactionReceipt(pendingTx)));
dispatch(getTransactionReceipt(tx));
}
}; };
// latestBlockFilter.watch(onBlockMined); // latestBlockFilter.watch(onBlockMined);
@ -220,7 +211,7 @@ export function getGasPrice(network: string): AsyncAction {
const index: number = getState().web3.findIndex(w3 => w3.network === network); const index: number = getState().web3.findIndex(w3 => w3.network === network);
const web3instance = getState().web3[index]; const web3instance = getState().web3[index];
const web3 = web3instance.web3; const { web3 } = web3instance;
web3.eth.getGasPrice((error, gasPrice) => { web3.eth.getGasPrice((error, gasPrice) => {
if (!error) { if (!error) {
if (web3instance.gasPrice && web3instance.gasPrice.toString() !== gasPrice.toString()) { if (web3instance.gasPrice && web3instance.gasPrice.toString() !== gasPrice.toString()) {
@ -238,7 +229,7 @@ export function getGasPrice(network: string): AsyncAction {
export function getBalance(account: Account): AsyncAction { export function getBalance(account: Account): AsyncAction {
return async (dispatch: Dispatch, getState: GetState): Promise<void> => { return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
const web3instance = getState().web3.filter(w3 => w3.network === account.network)[0]; const web3instance = getState().web3.filter(w3 => w3.network === account.network)[0];
const web3: Web3 = web3instance.web3; const { web3 } = web3instance;
web3.eth.getBalance(account.address, (error: Error, balance: BigNumber) => { web3.eth.getBalance(account.address, (error: Error, balance: BigNumber) => {
if (!error) { if (!error) {
@ -261,7 +252,6 @@ export function getBalance(account: Account): AsyncAction {
export function getTokenBalance(token: Token): AsyncAction { export function getTokenBalance(token: Token): AsyncAction {
return async (dispatch: Dispatch, getState: GetState): Promise<void> => { return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
const web3instance = getState().web3.filter(w3 => w3.network === token.network)[0]; const web3instance = getState().web3.filter(w3 => w3.network === token.network)[0];
const web3 = web3instance.web3;
const contract = web3instance.erc20.at(token.address); const contract = web3instance.erc20.at(token.address);
contract.balanceOf(token.ethAddress, (error: Error, balance: BigNumber) => { contract.balanceOf(token.ethAddress, (error: Error, balance: BigNumber) => {
@ -282,7 +272,7 @@ export function getTokenBalance(token: Token): AsyncAction {
export function getNonce(account: Account): AsyncAction { export function getNonce(account: Account): AsyncAction {
return async (dispatch: Dispatch, getState: GetState): Promise<void> => { return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
const web3instance = getState().web3.filter(w3 => w3.network === account.network)[0]; const web3instance = getState().web3.filter(w3 => w3.network === account.network)[0];
const web3 = web3instance.web3; const { web3 } = web3instance;
web3.eth.getTransactionCount(account.address, (error: Error, result: number) => { web3.eth.getTransactionCount(account.address, (error: Error, result: number) => {
if (!error) { if (!error) {
@ -296,7 +286,7 @@ export function getNonce(account: Account): AsyncAction {
export const getTransactionReceipt = (tx: PendingTx): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => { export const getTransactionReceipt = (tx: PendingTx): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => {
const web3instance = getState().web3.filter(w3 => w3.network === tx.network)[0]; const web3instance = getState().web3.filter(w3 => w3.network === tx.network)[0];
const web3 = web3instance.web3; const { web3 } = web3instance;
web3.eth.getTransaction(tx.id, (error: Error, status: TransactionStatus) => { web3.eth.getTransaction(tx.id, (error: Error, status: TransactionStatus) => {
if (!error && !status) { if (!error && !status) {
@ -367,8 +357,8 @@ export const getNonceAsync = (web3: Web3, address: string): Promise<number> => n
}); });
export const getTokenInfoAsync = (erc20: ContractFactory, address: string): Promise<?NetworkToken> => new Promise((resolve, reject) => { export const getTokenInfoAsync = (erc20: ContractFactory, address: string): Promise<?NetworkToken> => new Promise((resolve) => {
const contract = erc20.at(address, (error, res) => { const contract = erc20.at(address, (error/* , res */) => {
// console.warn("callback", error, res) // console.warn("callback", error, res)
}); });

View File

@ -1,7 +1,6 @@
import React from 'react'; import React from 'react';
import styled, { css } from 'styled-components'; import styled, { css } from 'styled-components';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Icon from 'components/Icon';
import colors from 'config/colors'; import colors from 'config/colors';
import { TRANSITION } from 'config/variables'; import { TRANSITION } from 'config/variables';
@ -118,9 +117,11 @@ const Button = ({
isWhite = false, isWhite = false,
isWebUsb = false, isWebUsb = false,
isTransparent = false, isTransparent = false,
}) => ( }) => {
const newClassName = isWebUsb ? `${className} trezor-webusb-button` : className;
return (
<Wrapper <Wrapper
className={className} className={newClassName}
onClick={onClick} onClick={onClick}
onMouseEnter={onMouseEnter} onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave} onMouseLeave={onMouseLeave}
@ -133,6 +134,7 @@ const Button = ({
{children} {children}
</Wrapper> </Wrapper>
); );
};
Button.propTypes = { Button.propTypes = {
children: PropTypes.node.isRequired, children: PropTypes.node.isRequired,

View File

@ -1,4 +1,3 @@
import React from 'react'; import React from 'react';
import { bindActionCreators } from 'redux'; import { bindActionCreators } from 'redux';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
@ -164,9 +163,9 @@ export const Notification = (props: NProps): React$Element<string> => {
export const NotificationGroup = (props) => { export const NotificationGroup = (props) => {
const { notifications, close } = props; const { notifications, close } = props;
return notifications.map((n, i) => ( return notifications.map(n => (
<Notification <Notification
key={i} key={n.title}
type={n.type} type={n.type}
title={n.title} title={n.title}
message={n.message} message={n.message}

View File

@ -11,11 +11,6 @@ const Wrapper = styled.div`
justify-content: flex-start; justify-content: flex-start;
`; `;
const Label = styled.span`
padding-bottom: 4px;
color: ${colors.TEXT_SECONDARY};
`;
const disabledColor = colors.TEXT_PRIMARY; const disabledColor = colors.TEXT_PRIMARY;
const TextArea = styled.textarea` const TextArea = styled.textarea`

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import styled, { css } from 'styled-components'; import styled from 'styled-components';
import colors from 'config/colors'; import colors from 'config/colors';
import Icon from 'components/Icon'; import Icon from 'components/Icon';
import { FONT_SIZE, FONT_WEIGHT } from 'config/variables'; import { FONT_SIZE, FONT_WEIGHT } from 'config/variables';

View File

@ -8,9 +8,8 @@ import colors from 'config/colors';
import icons from 'config/icons'; import icons from 'config/icons';
import Button from 'components/Button'; import Button from 'components/Button';
import Link from 'components/Link'; import Link from 'components/Link';
import { findAccount } from 'reducers/AccountsReducer';
import type { Props } from './index'; import type { Props } from '../../index';
const StyledLink = styled(Link)` const StyledLink = styled(Link)`
position: absolute; position: absolute;
@ -38,15 +37,6 @@ const StyledButton = styled(Button)`
`; `;
class ConfirmUnverifiedAddress extends Component<Props> { class ConfirmUnverifiedAddress extends Component<Props> {
keyboardHandler: (event: KeyboardEvent) => void;
keyboardHandler(event: KeyboardEvent): void {
if (event.keyCode === 13) {
event.preventDefault();
this.verifyAddress();
}
}
componentDidMount(): void { componentDidMount(): void {
this.keyboardHandler = this.keyboardHandler.bind(this); this.keyboardHandler = this.keyboardHandler.bind(this);
window.addEventListener('keydown', this.keyboardHandler, false); window.addEventListener('keydown', this.keyboardHandler, false);
@ -56,6 +46,15 @@ class ConfirmUnverifiedAddress extends Component<Props> {
window.removeEventListener('keydown', this.keyboardHandler, false); window.removeEventListener('keydown', this.keyboardHandler, false);
} }
keyboardHandler: (event: KeyboardEvent) => void;
keyboardHandler(event: KeyboardEvent): void {
if (event.keyCode === 13) {
event.preventDefault();
this.verifyAddress();
}
}
verifyAddress() { verifyAddress() {
if (!this.props.modal.opened) return; if (!this.props.modal.opened) return;
const { const {

View File

@ -63,12 +63,12 @@ const ErrorMessage = styled.div`
`; `;
export default class DuplicateDevice extends Component<Props, State> { export default class DuplicateDevice extends Component<Props, State> {
keyboardHandler: (event: KeyboardEvent) => void;
state: State; state: State;
input: ?HTMLInputElement; input: ?HTMLInputElement;
keyboardHandler: (event: KeyboardEvent) => void;
constructor(props: Props) { constructor(props: Props) {
super(props); super(props);
@ -85,13 +85,6 @@ export default class DuplicateDevice extends Component<Props, State> {
}; };
} }
keyboardHandler(event: KeyboardEvent): void {
if (event.keyCode === 13 && !this.state.isUsed) {
event.preventDefault();
this.submit();
}
}
componentDidMount(): void { componentDidMount(): void {
// one time autofocus // one time autofocus
if (this.input) this.input.focus(); if (this.input) this.input.focus();
@ -115,6 +108,13 @@ export default class DuplicateDevice extends Component<Props, State> {
}); });
} }
keyboardHandler(event: KeyboardEvent): void {
if (event.keyCode === 13 && !this.state.isUsed) {
event.preventDefault();
this.submit();
}
}
submit() { submit() {
if (!this.props.modal.opened) return; if (!this.props.modal.opened) return;
const extended: Object = { instanceName: this.state.instanceName, instance: this.state.instance }; const extended: Object = { instanceName: this.state.instanceName, instance: this.state.instance };
@ -125,7 +125,7 @@ export default class DuplicateDevice extends Component<Props, State> {
if (!this.props.modal.opened) return null; if (!this.props.modal.opened) return null;
const { device } = this.props.modal; const { device } = this.props.modal;
const { onCancel, onDuplicateDevice } = this.props.modalActions; const { onCancel } = this.props.modalActions;
const { const {
defaultName, defaultName,
instanceName, instanceName,

View File

@ -6,7 +6,7 @@ import P from 'components/Paragraph';
import Loader from 'components/Loader'; import Loader from 'components/Loader';
import Button from 'components/Button'; import Button from 'components/Button';
import type { Props } from './index'; import type { Props } from '../../index';
type State = { type State = {
countdown: number; countdown: number;
@ -77,9 +77,9 @@ export default class RememberDevice extends Component<Props, State> {
this.props.modalActions.onForgetDevice(this.props.modal.device); this.props.modalActions.onForgetDevice(this.props.modal.device);
} }
} else { } else {
this.setState({ this.setState(previousState => ({
countdown: this.state.countdown - 1, countdown: previousState.countdown - 1,
}); }));
} }
}; };
@ -108,16 +108,16 @@ export default class RememberDevice extends Component<Props, State> {
render() { render() {
if (!this.props.modal.opened) return null; if (!this.props.modal.opened) return null;
const { device, instances } = this.props.modal; const { device, instances } = this.props.modal;
const { onForgetDevice, onRememberDevice } = this.props.modalActions; const { onRememberDevice } = this.props.modalActions;
let label = device.label; let { label } = device;
const devicePlural: string = instances && instances.length > 1 ? 'devices or to remember them' : 'device or to remember it'; const devicePlural: string = instances && instances.length > 1 ? 'devices or to remember them' : 'device or to remember it';
if (instances && instances.length > 0) { if (instances && instances.length > 0) {
label = instances.map((instance, index) => { label = instances.map((instance, index) => {
let comma: string = ''; let comma: string = '';
if (index > 0) comma = ', '; if (index > 0) comma = ', ';
return ( return (
<span key={index}>{ comma }{ instance.instanceLabel }</span> <span key={instance.instanceLabel}>{ comma }{ instance.instanceLabel }</span>
); );
}); });
} }

View File

@ -9,8 +9,8 @@ import { CSSTransition } from 'react-transition-group';
import { UI } from 'trezor-connect'; import { UI } from 'trezor-connect';
import { default as ModalActions } from 'actions/ModalActions'; import ModalActions from 'actions/ModalActions';
import { default as ReceiveActions } from 'actions/ReceiveActions'; import ReceiveActions from 'actions/ReceiveActions';
import * as RECEIVE from 'actions/constants/receive'; import * as RECEIVE from 'actions/constants/receive';
import * as CONNECT from 'actions/constants/TrezorConnect'; import * as CONNECT from 'actions/constants/TrezorConnect';
@ -51,8 +51,6 @@ type DispatchProps = {
export type Props = StateProps & DispatchProps; export type Props = StateProps & DispatchProps;
const duration = 300;
const Fade = ({ children, ...props }) => ( const Fade = ({ children, ...props }) => (
<CSSTransition <CSSTransition
{...props} {...props}
@ -125,7 +123,8 @@ class Modal extends Component<Props> {
component = (<DuplicateDevice {...this.props} />); component = (<DuplicateDevice {...this.props} />);
break; break;
default: null; default:
component = null;
} }
let ch = null; let ch = null;
@ -145,7 +144,7 @@ class Modal extends Component<Props> {
} }
} }
const mapStateToProps: MapStateToProps<State, OwnProps, StateProps> = (state: State, own: OwnProps): StateProps => ({ const mapStateToProps: MapStateToProps<State, OwnProps, StateProps> = (state: State): StateProps => ({
modal: state.modal, modal: state.modal,
accounts: state.accounts, accounts: state.accounts,
devices: state.devices, devices: state.devices,

View File

@ -4,14 +4,13 @@ import raf from 'raf';
import colors from 'config/colors'; import colors from 'config/colors';
import P from 'components/Paragraph'; import P from 'components/Paragraph';
import { FONT_SIZE } from 'config/variables'; import { FONT_SIZE } from 'config/variables';
import { H2 } from 'components/Heading';
import Link from 'components/Link'; import Link from 'components/Link';
import Checkbox from 'components/Checkbox'; import Checkbox from 'components/Checkbox';
import Button from 'components/Button'; import Button from 'components/Button';
import Input from 'components/inputs/Input'; import Input from 'components/inputs/Input';
import styled from 'styled-components'; import styled from 'styled-components';
import type { Props } from './index'; import type { Props } from '../../index';
const Wrapper = styled.div` const Wrapper = styled.div`
padding: 24px 48px; padding: 24px 48px;
@ -55,14 +54,6 @@ type State = {
} }
export default class PinModal extends Component<Props, State> { export default class PinModal extends Component<Props, State> {
keyboardHandler: (event: KeyboardEvent) => void;
state: State;
passphraseInput: ?HTMLInputElement;
passphraseRevisionInput: ?HTMLInputElement;
constructor(props: Props) { constructor(props: Props) {
super(props); super(props);
@ -91,6 +82,15 @@ export default class PinModal extends Component<Props, State> {
}; };
} }
keyboardHandler: (event: KeyboardEvent) => void;
state: State;
passphraseInput: ?HTMLInputElement;
passphraseRevisionInput: ?HTMLInputElement;
keyboardHandler(event: KeyboardEvent): void { keyboardHandler(event: KeyboardEvent): void {
if (event.keyCode === 13) { if (event.keyCode === 13) {
event.preventDefault(); event.preventDefault();
@ -108,6 +108,7 @@ export default class PinModal extends Component<Props, State> {
} }
} }
componentDidMount(): void { componentDidMount(): void {
// one time autofocus // one time autofocus
if (this.passphraseInput) this.passphraseInput.focus(); if (this.passphraseInput) this.passphraseInput.focus();
@ -124,15 +125,6 @@ export default class PinModal extends Component<Props, State> {
// }; // };
} }
componentWillUnmount(): void {
window.removeEventListener('keydown', this.keyboardHandler, false);
// this.passphraseInput.type = 'text';
// this.passphraseInput.style.display = 'none';
// this.passphraseRevisionInput.type = 'text';
// this.passphraseRevisionInput.style.display = 'none';
}
// we don't want to keep password inside "value" attribute, // we don't want to keep password inside "value" attribute,
// so we need to replace it thru javascript // so we need to replace it thru javascript
componentDidUpdate() { componentDidUpdate() {
@ -164,21 +156,30 @@ export default class PinModal extends Component<Props, State> {
} }
} }
componentWillUnmount(): void {
window.removeEventListener('keydown', this.keyboardHandler, false);
// this.passphraseInput.type = 'text';
// this.passphraseInput.style.display = 'none';
// this.passphraseRevisionInput.type = 'text';
// this.passphraseRevisionInput.style.display = 'none';
}
onPassphraseChange = (input: string, value: string): void => { onPassphraseChange = (input: string, value: string): void => {
// https://codepen.io/MiDri/pen/PGqvrO // https://codepen.io/MiDri/pen/PGqvrO
// or // or
// https://github.com/zakangelle/react-password-mask/blob/master/src/index.js // https://github.com/zakangelle/react-password-mask/blob/master/src/index.js
if (input === 'passphrase') { if (input === 'passphrase') {
this.setState({ this.setState(previousState => ({
match: this.state.singleInput || this.state.passphraseRevision === value, match: previousState.singleInput || previousState.passphraseRevision === value,
passphrase: value, passphrase: value,
}); }));
} else { } else {
this.setState({ this.setState(previousState => ({
match: this.state.passphrase === value, match: previousState.passphrase === value,
passphraseRevision: value, passphraseRevision: value,
passphraseRevisionTouched: true, passphraseRevisionTouched: true,
}); }));
} }
} }

View File

@ -3,7 +3,7 @@ import styled from 'styled-components';
import { H3 } from 'components/Heading'; import { H3 } from 'components/Heading';
import P from 'components/Paragraph'; import P from 'components/Paragraph';
import type { Props } from './index'; import type { Props } from '../../index';
const Wrapper = styled.div` const Wrapper = styled.div`
padding: 24px 48px; padding: 24px 48px;

View File

@ -3,12 +3,11 @@ import P from 'components/Paragraph';
import { H2 } from 'components/Heading'; import { H2 } from 'components/Heading';
import React, { Component } from 'react'; import React, { Component } from 'react';
import Link from 'components/Link'; import Link from 'components/Link';
import colors from 'config/colors';
import styled from 'styled-components'; import styled from 'styled-components';
import PinInput from 'components/inputs/PinInput'; import PinInput from 'components/inputs/PinInput';
import Button from 'components/Button'; import Button from 'components/Button';
import PinButton from './components/PinButton'; import PinButton from './components/PinButton';
import type { Props } from './index'; import type { Props } from '../../index';
type State = { type State = {
pin: string; pin: string;
@ -53,7 +52,7 @@ class Pin extends Component<Props, State> {
} }
onPinAdd = (input: number): void => { onPinAdd = (input: number): void => {
let pin: string = this.state.pin; let { pin } = this.state;
if (pin.length < 9) { if (pin.length < 9) {
pin += input; pin += input;
this.setState({ this.setState({
@ -63,9 +62,9 @@ class Pin extends Component<Props, State> {
} }
onPinBackspace = (): void => { onPinBackspace = (): void => {
this.setState({ this.setState(previousState => ({
pin: this.state.pin.substring(0, this.state.pin.length - 1), pin: previousState.pin.substring(0, previousState.pin.length - 1),
}); }));
} }
keyboardHandler(event: KeyboardEvent): void { keyboardHandler(event: KeyboardEvent): void {

View File

@ -7,11 +7,10 @@ import type {
Middleware as ReduxMiddleware, Middleware as ReduxMiddleware,
ThunkAction as ReduxThunkAction, ThunkAction as ReduxThunkAction,
AsyncAction as ReduxAsyncAction, AsyncAction as ReduxAsyncAction,
ThunkDispatch as ReduxThunkDispatch,
PlainDispatch as ReduxPlainDispatch, PlainDispatch as ReduxPlainDispatch,
} from 'redux'; } from 'redux';
import type { Reducers, ReducersState } from 'reducers'; import type { ReducersState } from 'reducers';
// Actions // Actions
import type { SelectedAccountAction } from 'actions/SelectedAccountActions'; import type { SelectedAccountAction } from 'actions/SelectedAccountActions';

View File

@ -22,7 +22,7 @@ const mergeDevices = (current: TrezorDevice, upcoming: Device | TrezorDevice): T
// } // }
// } // }
let instanceLabel = current.instanceLabel; let { instanceLabel } = current;
if (upcoming.label !== current.label) { if (upcoming.label !== current.label) {
instanceLabel = upcoming.label; instanceLabel = upcoming.label;
if (typeof current.instance === 'number') { if (typeof current.instance === 'number') {

View File

@ -62,9 +62,10 @@ const closeNotification = (state: State, payload: any): State => {
export default function notification(state: State = initialState, action: Action): State { export default function notification(state: State = initialState, action: Action): State {
switch (action.type) { switch (action.type) {
case DEVICE.DISCONNECT: case DEVICE.DISCONNECT: {
const path: string = action.device.path; // Flow warning const { path } = action.device; // Flow warning
return state.filter(entry => entry.devicePath !== path); return state.filter(entry => entry.devicePath !== path);
}
case NOTIFICATION.ADD: case NOTIFICATION.ADD:
return addNotification(state, action.payload); return addNotification(state, action.payload);

View File

@ -1,9 +1,6 @@
/* @flow */ /* @flow */
import * as PENDING from 'actions/constants/pendingTx'; import * as PENDING from 'actions/constants/pendingTx';
import * as SEND from 'actions/constants/send'; import * as SEND from 'actions/constants/send';
import * as WEB3 from 'actions/constants/web3';
import type { Action } from 'flowtype'; import type { Action } from 'flowtype';
import type { SendTxAction } from 'actions/SendFormActions'; import type { SendTxAction } from 'actions/SendFormActions';

View File

@ -2,11 +2,9 @@
import EthereumjsUnits from 'ethereumjs-units'; import EthereumjsUnits from 'ethereumjs-units';
import BigNumber from 'bignumber.js';
import * as SEND from 'actions/constants/send'; import * as SEND from 'actions/constants/send';
import * as WEB3 from 'actions/constants/web3'; import * as WEB3 from 'actions/constants/web3';
import * as ACCOUNT from 'actions/constants/account'; import * as ACCOUNT from 'actions/constants/account';
import * as WALLET from 'actions/constants/wallet';
import { getFeeLevels } from 'actions/SendFormActions'; import { getFeeLevels } from 'actions/SendFormActions';
@ -15,6 +13,12 @@ import type {
Web3UpdateGasPriceAction, Web3UpdateGasPriceAction,
} from 'actions/Web3Actions'; } from 'actions/Web3Actions';
export type FeeLevel = {
label: string;
gasPrice: string;
value: string;
}
export type State = { export type State = {
+networkName: string; +networkName: string;
+networkSymbol: string; +networkSymbol: string;
@ -45,12 +49,6 @@ export type State = {
sending: boolean; sending: boolean;
} }
export type FeeLevel = {
label: string;
gasPrice: string;
value: string;
}
export const initialState: State = { export const initialState: State = {
networkName: '', networkName: '',

View File

@ -1,9 +1,6 @@
/* @flow */ /* @flow */
import { TRANSPORT, UI } from 'trezor-connect';
import { TRANSPORT, DEVICE, UI } from 'trezor-connect';
import * as CONNECT from 'actions/constants/TrezorConnect'; import * as CONNECT from 'actions/constants/TrezorConnect';
import * as WALLET from 'actions/constants/wallet';
import type { Action } from 'flowtype'; import type { Action } from 'flowtype';

View File

@ -17,7 +17,7 @@ export const getSelectedDevice = (state: State): ?TrezorDevice => {
const locationState = state.router.location.state; const locationState = state.router.location.state;
if (!locationState.device) return undefined; if (!locationState.device) return undefined;
const instance: ?number = locationState.deviceInstance ? parseInt(locationState.deviceInstance) : undefined; const instance: ?number = locationState.deviceInstance ? parseInt(locationState.deviceInstance, 10) : undefined;
return state.devices.find((d) => { return state.devices.find((d) => {
if (!d.features && d.path === locationState.device) { if (!d.features && d.path === locationState.device) {
return true; return true;
@ -64,14 +64,14 @@ export const getSelectedAccount = (state: State): ?Account => {
const locationState = state.router.location.state; const locationState = state.router.location.state;
if (!device || !locationState.network || !locationState.account) return null; if (!device || !locationState.network || !locationState.account) return null;
const index: number = parseInt(locationState.account); const index: number = parseInt(locationState.account, 10);
return state.accounts.find(a => a.deviceState === device.state && a.index === index && a.network === locationState.network); return state.accounts.find(a => a.deviceState === device.state && a.index === index && a.network === locationState.network);
}; };
export const getSelectedNetwork = (state: State): ?Coin => { export const getSelectedNetwork = (state: State): ?Coin => {
const device = state.wallet.selectedDevice; const device = state.wallet.selectedDevice;
const coins = state.localStorage.config.coins; const { coins } = state.localStorage.config;
const locationState = state.router.location.state; const locationState = state.router.location.state;
if (!device || !locationState.network) return null; if (!device || !locationState.network) return null;

View File

@ -1,6 +1,6 @@
/* @flow */ /* @flow */
import { JSONRequest, httpRequest } from 'utils/networkUtils'; import { httpRequest } from 'utils/networkUtils';
import { resolveAfter } from 'utils/promiseUtils'; import { resolveAfter } from 'utils/promiseUtils';
import { READY } from 'actions/constants/localStorage'; import { READY } from 'actions/constants/localStorage';
@ -8,7 +8,6 @@ import type {
Middleware, Middleware,
MiddlewareAPI, MiddlewareAPI,
MiddlewareDispatch, MiddlewareDispatch,
State,
Dispatch, Dispatch,
Action, Action,
AsyncAction, AsyncAction,

View File

@ -1,18 +1,13 @@
/* @flow */ /* @flow */
import { DEVICE } from 'trezor-connect'; import { DEVICE } from 'trezor-connect';
import { LOCATION_CHANGE } from 'react-router-redux';
import * as LocalStorageActions from 'actions/LocalStorageActions'; import * as LocalStorageActions from 'actions/LocalStorageActions';
import * as WalletActions from 'actions/WalletActions'; // import * as WalletActions from 'actions/WalletActions';
import * as CONNECT from 'actions/constants/TrezorConnect'; import * as CONNECT from 'actions/constants/TrezorConnect';
import * as MODAL from 'actions/constants/modal';
import * as TOKEN from 'actions/constants/token'; import * as TOKEN from 'actions/constants/token';
import * as ACCOUNT from 'actions/constants/account'; import * as ACCOUNT from 'actions/constants/account';
import * as DISCOVERY from 'actions/constants/discovery'; import * as DISCOVERY from 'actions/constants/discovery';
import * as SEND from 'actions/constants/send'; import * as SEND from 'actions/constants/send';
import * as WEB3 from 'actions/constants/web3';
import * as PENDING from 'actions/constants/pendingTx'; import * as PENDING from 'actions/constants/pendingTx';
import { findAccountTokens } from 'reducers/TokensReducer'; import { findAccountTokens } from 'reducers/TokensReducer';
@ -20,14 +15,12 @@ import type {
Middleware, Middleware,
MiddlewareAPI, MiddlewareAPI,
MiddlewareDispatch, MiddlewareDispatch,
State,
Dispatch, Dispatch,
Action, Action,
AsyncAction,
GetState, GetState,
TrezorDevice,
} from 'flowtype'; } from 'flowtype';
import type { TrezorDevice } from 'flowtype';
import type { Account } from 'reducers/AccountsReducer'; import type { Account } from 'reducers/AccountsReducer';
import type { Token } from 'reducers/TokensReducer'; import type { Token } from 'reducers/TokensReducer';
import type { PendingTx } from 'reducers/PendingTxReducer'; import type { PendingTx } from 'reducers/PendingTxReducer';

View File

@ -1,29 +1,23 @@
/* @flow */ /* @flow */
import * as LogActions from 'actions/LogActions'; import * as LogActions from 'actions/LogActions';
import * as STORAGE from 'actions/constants/localStorage'; // import * as STORAGE from 'actions/constants/localStorage';
import * as SEND from 'actions/constants/send'; // import * as SEND from 'actions/constants/send';
import { OPEN, CLOSE, ADD } from 'actions/constants/log'; // import { OPEN, CLOSE, ADD } from 'actions/constants/log';
import { TRANSPORT, DEVICE } from 'trezor-connect'; import { TRANSPORT, DEVICE } from 'trezor-connect';
import type { import type {
Middleware, Middleware,
MiddlewareAPI, MiddlewareAPI,
MiddlewareDispatch, MiddlewareDispatch,
State,
Dispatch,
Action, Action,
AsyncAction,
GetState,
} from 'flowtype'; } from 'flowtype';
const exclude: Array<string> = [ // const exclude: Array<string> = [
ADD, OPEN, CLOSE, // ADD, OPEN, CLOSE,
STORAGE.READY, // STORAGE.READY,
SEND.TX_COMPLETE, // SEND.TX_COMPLETE,
'web3__create', // 'web3__create',
]; // ];
const include: Array<string> = [ const include: Array<string> = [
TRANSPORT.START, TRANSPORT.START,

View File

@ -1,8 +1,5 @@
/* @flow */ /* @flow */
import { LOCATION_CHANGE/* , replace */ } from 'react-router-redux';
import { DEVICE } from 'trezor-connect';
import { LOCATION_CHANGE, push, replace } from 'react-router-redux';
import * as CONNECT from 'actions/constants/TrezorConnect'; import * as CONNECT from 'actions/constants/TrezorConnect';
import * as WALLET from 'actions/constants/wallet'; import * as WALLET from 'actions/constants/wallet';
import * as NotificationActions from 'actions/NotificationActions'; import * as NotificationActions from 'actions/NotificationActions';
@ -11,12 +8,7 @@ import type {
Middleware, Middleware,
MiddlewareAPI, MiddlewareAPI,
MiddlewareDispatch, MiddlewareDispatch,
State,
Dispatch,
Action, Action,
ThunkAction,
AsyncAction,
GetState,
RouterLocationState, RouterLocationState,
TrezorDevice, TrezorDevice,
} from 'flowtype'; } from 'flowtype';
@ -51,7 +43,7 @@ const validation = (api: MiddlewareAPI, params: RouterLocationState): boolean =>
let device: ?TrezorDevice; let device: ?TrezorDevice;
if (params.hasOwnProperty('deviceInstance')) { if (params.hasOwnProperty('deviceInstance')) {
device = devices.find(d => d.features && d.features.device_id === params.device && d.instance === parseInt(params.deviceInstance)); device = devices.find(d => d.features && d.features.device_id === params.device && d.instance === parseInt(params.deviceInstance, 10));
} else { } else {
device = devices.find(d => d.path === params.device || (d.features && d.features.device_id === params.device)); device = devices.find(d => d.path === params.device || (d.features && d.features.device_id === params.device));
} }
@ -61,25 +53,20 @@ const validation = (api: MiddlewareAPI, params: RouterLocationState): boolean =>
if (params.hasOwnProperty('network')) { if (params.hasOwnProperty('network')) {
const { config } = api.getState().localStorage; const { config } = api.getState().localStorage;
const coin = config.coins.find(coin => coin.network === params.network); const coin = config.coins.find(c => c.network === params.network);
if (!coin) return false; if (!coin) return false;
if (!params.account) return false; if (!params.account) return false;
} }
if (params.account) { // if (params.account) {
} // }
return true; return true;
}; };
let __unloading: boolean = false; let __unloading: boolean = false;
const LandingURLS: Array<string> = [
'/',
'/bridge',
];
const RouterService: Middleware = (api: MiddlewareAPI) => (next: MiddlewareDispatch) => (action: Action): Action => { const RouterService: Middleware = (api: MiddlewareAPI) => (next: MiddlewareDispatch) => (action: Action): Action => {
if (action.type === WALLET.ON_BEFORE_UNLOAD) { if (action.type === WALLET.ON_BEFORE_UNLOAD) {
__unloading = true; __unloading = true;

View File

@ -1,10 +1,8 @@
/* @flow */ /* @flow */
import { push } from 'react-router-redux'; import { push } from 'react-router-redux';
import TrezorConnect, { import {
TRANSPORT, DEVICE_EVENT, UI_EVENT, UI, DEVICE, TRANSPORT, DEVICE,
} from 'trezor-connect'; } from 'trezor-connect';
import * as TrezorConnectActions from 'actions/TrezorConnectActions'; import * as TrezorConnectActions from 'actions/TrezorConnectActions';
import * as DiscoveryActions from 'actions/DiscoveryActions'; import * as DiscoveryActions from 'actions/DiscoveryActions';
@ -13,25 +11,19 @@ import { init as initWeb3 } from 'actions/Web3Actions';
import * as WEB3 from 'actions/constants/web3'; import * as WEB3 from 'actions/constants/web3';
import * as STORAGE from 'actions/constants/localStorage'; import * as STORAGE from 'actions/constants/localStorage';
import * as CONNECT from 'actions/constants/TrezorConnect'; import * as CONNECT from 'actions/constants/TrezorConnect';
import * as NOTIFICATION from 'actions/constants/notification';
import * as MODAL from 'actions/constants/modal';
import type { import type {
Middleware, Middleware,
MiddlewareAPI, MiddlewareAPI,
MiddlewareDispatch, MiddlewareDispatch,
State, State,
Dispatch,
Action, Action,
AsyncAction,
GetState,
RouterLocationState,
} from 'flowtype'; } from 'flowtype';
const TrezorConnectService: Middleware = (api: MiddlewareAPI) => (next: MiddlewareDispatch) => (action: Action): Action => { const TrezorConnectService: Middleware = (api: MiddlewareAPI) => (next: MiddlewareDispatch) => (action: Action): Action => {
const prevState: $ElementType<State, 'connect'> = api.getState().connect; // const prevState: $ElementType<State, 'connect'> = api.getState().connect;
const prevModalState: $ElementType<State, 'modal'> = api.getState().modal; const prevModalState: $ElementType<State, 'modal'> = api.getState().modal;
const prevRouterState: $ElementType<State, 'router'> = api.getState().router; // const prevRouterState: $ElementType<State, 'router'> = api.getState().router;
next(action); next(action);

View File

@ -1,19 +1,18 @@
/* @flow */ /* @flow */
import { createStore, applyMiddleware, compose } from 'redux'; import { createStore, applyMiddleware, compose } from 'redux';
import { routerMiddleware, push } from 'react-router-redux'; import { routerMiddleware } from 'react-router-redux';
import thunk from 'redux-thunk'; import thunk from 'redux-thunk';
// import createHistory from 'history/createBrowserHistory'; // import createHistory from 'history/createBrowserHistory';
// import { useRouterHistory } from 'react-router'; // import { useRouterHistory } from 'react-router';
import createHistory from 'history/createHashHistory'; import createHistory from 'history/createHashHistory';
import { createLogger } from 'redux-logger';
import reducers from 'reducers'; import reducers from 'reducers';
import services from 'services'; import services from 'services';
import Raven from 'raven-js'; import Raven from 'raven-js';
import RavenMiddleware from 'redux-raven-middleware'; import RavenMiddleware from 'redux-raven-middleware';
import type { Action, GetState, Store } from 'flowtype'; // import type { Action, GetState, Store } from 'flowtype';
export const history: History = createHistory({ queryKey: false }); export const history: History = createHistory({ queryKey: false });
@ -31,12 +30,12 @@ const middleware = [
let composedEnhancers: any; let composedEnhancers: any;
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
const excludeLogger = (getState: GetState, action: Action): boolean => { // const excludeLogger = (getState: GetState, action: Action): boolean => {
//'@@router/LOCATION_CHANGE' // //'@@router/LOCATION_CHANGE'
const excluded: Array<string> = ['LOG_TO_EXCLUDE', 'log__add']; // const excluded: Array<string> = ['LOG_TO_EXCLUDE', 'log__add'];
const pass: Array<string> = excluded.filter(act => action.type === act); // const pass: Array<string> = excluded.filter(act => action.type === act);
return pass.length === 0; // return pass.length === 0;
}; // };
composedEnhancers = compose( composedEnhancers = compose(
applyMiddleware(...middleware, ...services), applyMiddleware(...middleware, ...services),

View File

@ -1,4 +1,5 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types';
import RedBox from 'redbox-react'; import RedBox from 'redbox-react';
class ErrorBoundary extends Component { class ErrorBoundary extends Component {
@ -7,7 +8,7 @@ class ErrorBoundary extends Component {
this.state = { hasError: false, error: false }; this.state = { hasError: false, error: false };
} }
componentDidCatch(error, info) { componentDidCatch(error) {
this.setState({ hasError: true, error }); this.setState({ hasError: true, error });
} }
@ -19,4 +20,8 @@ class ErrorBoundary extends Component {
} }
} }
ErrorBoundary.propTypes = {
children: PropTypes.node,
};
export default ErrorBoundary; export default ErrorBoundary;

View File

@ -4,9 +4,9 @@ import BigNumber from 'bignumber.js';
export const decimalToHex = (dec: number): string => new BigNumber(dec).toString(16); export const decimalToHex = (dec: number): string => new BigNumber(dec).toString(16);
export const hexToDecimal = (hex: number): string => { export const padLeftEven = (hex: string): string => {
const sanitized: ?string = sanitizeHex(hex); hex = hex.length % 2 != 0 ? `0${hex}` : hex;
return !sanitized ? 'null' : new BigNumber(sanitized).toString(); return hex;
}; };
export const sanitizeHex = (hex: number | string): ?string => { export const sanitizeHex = (hex: number | string): ?string => {
@ -16,9 +16,9 @@ export const sanitizeHex = (hex: number | string): ?string => {
return `0x${padLeftEven(hex)}`; return `0x${padLeftEven(hex)}`;
}; };
export const padLeftEven = (hex: string): string => { export const hexToDecimal = (hex: number): string => {
hex = hex.length % 2 != 0 ? `0${hex}` : hex; const sanitized: ?string = sanitizeHex(hex);
return hex; return !sanitized ? 'null' : new BigNumber(sanitized).toString();
}; };
export const strip = (str: string): string => { export const strip = (str: string): string => {

View File

@ -28,7 +28,7 @@ export const formatTime = (n: number): string => {
} }
res += ' '; res += ' ';
} }
if (minutes != 0) { if (minutes !== 0) {
res += `${minutes} minutes`; res += `${minutes} minutes`;
} }
return res; return res;

View File

@ -1,7 +1,4 @@
/* @flow */ /* @flow */
import React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import type { MapStateToProps, MapDispatchToProps } from 'react-redux'; import type { MapStateToProps, MapDispatchToProps } from 'react-redux';
@ -39,7 +36,7 @@ const mapStateToProps: MapStateToProps<State, OwnProps, StateProps> = (state: St
devices: state.devices, devices: state.devices,
}); });
const mapDispatchToProps: MapDispatchToProps<Dispatch, OwnProps, DispatchProps> = (dispatch: Dispatch): DispatchProps => ({ const mapDispatchToProps: MapDispatchToProps<Dispatch, OwnProps, DispatchProps> = (/* dispatch: Dispatch */): DispatchProps => ({
}); });

View File

@ -89,7 +89,9 @@ class ConnectDevice extends Component<Props> {
{this.props.showWebUsb && ( {this.props.showWebUsb && (
<React.Fragment> <React.Fragment>
<P>and</P> <P>and</P>
<Button isWebUsb>Check for devices</Button> <Button isWebUsb>
Check for devices
</Button>
</React.Fragment> </React.Fragment>
)} )}
</Wrapper> </Wrapper>

View File

@ -13,18 +13,18 @@ import P from 'components/Paragraph';
import Icon from 'components/Icon'; import Icon from 'components/Icon';
import ICONS from 'config/icons'; import ICONS from 'config/icons';
type State = {
version: string;
target: ?InstallTarget;
url: string;
}
type InstallTarget = { type InstallTarget = {
id: string; id: string;
value: string; value: string;
label: string; label: string;
} }
type State = {
version: string;
target: ?InstallTarget;
url: string;
}
// import type { Props } from './index'; // import type { Props } from './index';
type Props = { type Props = {

View File

@ -138,7 +138,7 @@ export default (props: Props) => {
)} )}
<P> <P>
<LandingFooterTextWrapper> <LandingFooterTextWrapper>
Don't have TREZOR? Don&amp;t have TREZOR?
</LandingFooterTextWrapper> </LandingFooterTextWrapper>
<StyledLink <StyledLink
href="https://trezor.io/" href="https://trezor.io/"

View File

@ -16,7 +16,7 @@ type OwnProps = {
} }
const mapStateToProps: MapStateToProps<State, OwnProps, StateProps> = (state: State, own: OwnProps): StateProps => ({ const mapStateToProps: MapStateToProps<State, OwnProps, StateProps> = (state: State/* , own: OwnProps */): StateProps => ({
connect: state.connect, connect: state.connect,
accounts: state.accounts, accounts: state.accounts,
router: state.router, router: state.router,

View File

@ -4,7 +4,6 @@ import BigNumber from 'bignumber.js';
import Icon from 'components/Icon'; import Icon from 'components/Icon';
import colors from 'config/colors'; import colors from 'config/colors';
import Loader from 'components/Loader'; import Loader from 'components/Loader';
import PropTypes from 'prop-types';
import styled, { css } from 'styled-components'; import styled, { css } from 'styled-components';
import * as stateUtils from 'reducers/utils'; import * as stateUtils from 'reducers/utils';
import Tooltip from 'components/Tooltip'; import Tooltip from 'components/Tooltip';

View File

@ -24,7 +24,7 @@ class DeviceList extends Component {
device !== selectedDevice && ( device !== selectedDevice && (
<DeviceHeader <DeviceHeader
key={`${device.instanceLabel}`} key={`${device.instanceLabel}`}
onClickWrapper={() => this.props.onSelectDevice(device)} onClickWrapper={() => onSelectDevice(device)}
onClickIcon={() => this.onDeviceMenuClick({ type: 'forget', label: '' }, device)} onClickIcon={() => this.onDeviceMenuClick({ type: 'forget', label: '' }, device)}
icon={( icon={(
<IconClick onClick={(event) => { <IconClick onClick={(event) => {

View File

@ -3,7 +3,6 @@ import React, { Component } from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import TrezorConnect from 'trezor-connect'; import TrezorConnect from 'trezor-connect';
import type { TrezorDevice } from 'flowtype'; import type { TrezorDevice } from 'flowtype';
import DeviceHeader from 'components/DeviceHeader';
import Button from 'components/Button'; import Button from 'components/Button';
import { isWebUSB } from 'utils/device'; import { isWebUSB } from 'utils/device';
import MenuItems from './components/MenuItems'; import MenuItems from './components/MenuItems';
@ -39,6 +38,13 @@ class DeviceMenu extends Component<Props> {
this.blurHandler = this.blurHandler.bind(this); this.blurHandler = this.blurHandler.bind(this);
} }
componentDidMount(): void {
window.addEventListener('mousedown', this.mouseDownHandler, false);
// window.addEventListener('blur', this.blurHandler, false);
const { transport } = this.props.connect;
if (transport && transport.version.indexOf('webusb') >= 0) TrezorConnect.renderWebUSBButton();
}
componentDidUpdate() { componentDidUpdate() {
const { transport } = this.props.connect; const { transport } = this.props.connect;
if (isWebUSB(transport)) TrezorConnect.renderWebUSBButton(); if (isWebUSB(transport)) TrezorConnect.renderWebUSBButton();
@ -61,17 +67,10 @@ class DeviceMenu extends Component<Props> {
} }
} }
blurHandler(event: FocusEvent): void { blurHandler(): void {
this.props.toggleDeviceDropdown(false); this.props.toggleDeviceDropdown(false);
} }
componentDidMount(): void {
window.addEventListener('mousedown', this.mouseDownHandler, false);
// window.addEventListener('blur', this.blurHandler, false);
const { transport } = this.props.connect;
if (transport && transport.version.indexOf('webusb') >= 0) TrezorConnect.renderWebUSBButton();
}
onDeviceMenuClick(item: DeviceMenuItem, device: TrezorDevice): void { onDeviceMenuClick(item: DeviceMenuItem, device: TrezorDevice): void {
if (item.type === 'reload') { if (item.type === 'reload') {
this.props.acquireDevice(); this.props.acquireDevice();

View File

@ -15,8 +15,6 @@ const Wrapper = styled.div`
class Indicator extends Component<Props, State> { class Indicator extends Component<Props, State> {
reposition: () => void; reposition: () => void;
state: State;
constructor(props: Props) { constructor(props: Props) {
super(props); super(props);
@ -30,6 +28,8 @@ class Indicator extends Component<Props, State> {
this.reposition = this.reposition.bind(this); this.reposition = this.reposition.bind(this);
} }
state: State;
handleResize() { handleResize() {
this.reposition(); this.reposition();
} }
@ -43,7 +43,7 @@ class Indicator extends Component<Props, State> {
window.removeEventListener('resize', this.reposition, false); window.removeEventListener('resize', this.reposition, false);
} }
componentDidUpdate(newProps: Props) { componentDidUpdate() {
this.reposition(); this.reposition();
} }

View File

@ -37,7 +37,7 @@ const StyledNavLink = styled(NavLink)`
`; `;
const TopNavigationAccount = (props: any) => { const TopNavigationAccount = (props) => {
const urlParams = props.match.params; const urlParams = props.match.params;
const basePath = `/device/${urlParams.device}/network/${urlParams.network}/account/${urlParams.account}`; const basePath = `/device/${urlParams.device}/network/${urlParams.network}/account/${urlParams.account}`;

View File

@ -20,13 +20,13 @@ import TopNavigationAccount from './components/TopNavigationAccount';
import TopNavigationDeviceSettings from './components/TopNavigationDeviceSettings'; import TopNavigationDeviceSettings from './components/TopNavigationDeviceSettings';
type WalletContainerProps = { type WalletContainerProps = {
wallet: $ElementType<State, 'wallet'>, // wallet: $ElementType<State, 'wallet'>,
children?: React.Node children?: React.Node
} }
type ContentProps = { // type ContentProps = {
children?: React.Node // children?: React.Node
} // }
const AppWrapper = styled.div` const AppWrapper = styled.div`
position: relative; position: relative;
@ -101,7 +101,7 @@ const Wallet = (props: WalletContainerProps) => (
</AppWrapper> </AppWrapper>
); );
const mapStateToProps: MapStateToProps<State, {}, WalletContainerProps> = (state: State, own: {}): WalletContainerProps => ({ const mapStateToProps: MapStateToProps<State, {}, WalletContainerProps> = (state: State): WalletContainerProps => ({
wallet: state.wallet, wallet: state.wallet,
}); });

View File

@ -24,7 +24,7 @@ type DispatchProps = BaseDispatchProps & {
export type Props = StateProps & BaseStateProps & DispatchProps & BaseDispatchProps; export type Props = StateProps & BaseStateProps & DispatchProps & BaseDispatchProps;
const mapStateToProps: MapStateToProps<State, OwnProps, StateProps> = (state: State, own: OwnProps): StateProps => ({ const mapStateToProps: MapStateToProps<State, OwnProps, StateProps> = (state: State): StateProps => ({
className: 'receive', className: 'receive',
selectedAccount: state.selectedAccount, selectedAccount: state.selectedAccount,
wallet: state.wallet, wallet: state.wallet,

View File

@ -25,6 +25,7 @@ const AddressWrapper = styled.div`
padding: 0px 48px; padding: 0px 48px;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
flex-direction: ${props => (props.isShowingQrCode ? 'column' : 'row')};
`; `;
const ValueWrapper = styled.div` const ValueWrapper = styled.div`
@ -139,7 +140,9 @@ const AccountReceive = (props: Props) => {
<SelectedAccount {...props}> <SelectedAccount {...props}>
<Wrapper> <Wrapper>
<StyledH2>Receive Ethereum or tokens</StyledH2> <StyledH2>Receive Ethereum or tokens</StyledH2>
<AddressWrapper> <AddressWrapper
isShowingQrCode={addressVerified || addressUnverified}
>
{isAddressVerifying && ( {isAddressVerifying && (
<AddressInfoText>Confirm address on TREZOR</AddressInfoText> <AddressInfoText>Confirm address on TREZOR</AddressInfoText>
)} )}

View File

@ -5,7 +5,7 @@ import * as React from 'react';
import { bindActionCreators } from 'redux'; import { bindActionCreators } from 'redux';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { default as SendFormActions } from 'actions/SendFormActions'; import SendFormActions from 'actions/SendFormActions';
import * as SessionStorageActions from 'actions/SessionStorageActions'; import * as SessionStorageActions from 'actions/SessionStorageActions';
import type { MapStateToProps, MapDispatchToProps } from 'react-redux'; import type { MapStateToProps, MapDispatchToProps } from 'react-redux';
import type { State, Dispatch } from 'flowtype'; import type { State, Dispatch } from 'flowtype';
@ -29,7 +29,7 @@ export type DispatchProps = BaseDispatchProps & {
export type Props = StateProps & BaseStateProps & DispatchProps & BaseDispatchProps; export type Props = StateProps & BaseStateProps & DispatchProps & BaseDispatchProps;
const mapStateToProps: MapStateToProps<State, OwnProps, StateProps> = (state: State, own: OwnProps): StateProps => ({ const mapStateToProps: MapStateToProps<State, OwnProps, StateProps> = (state: State): StateProps => ({
className: 'send-from', className: 'send-from',
selectedAccount: state.selectedAccount, selectedAccount: state.selectedAccount,
wallet: state.wallet, wallet: state.wallet,

View File

@ -9,7 +9,7 @@ import ScaleText from 'react-scale-text';
import type { Coin } from 'reducers/LocalStorageReducer'; import type { Coin } from 'reducers/LocalStorageReducer';
import type { Token } from 'reducers/TokensReducer'; import type { Token } from 'reducers/TokensReducer';
import type { Props as BaseProps } from '../Container'; import type { Props as BaseProps } from '../../Container';
type Props = { type Props = {
pending: $PropertyType<$ElementType<BaseProps, 'selectedAccount'>, 'pending'>, pending: $PropertyType<$ElementType<BaseProps, 'selectedAccount'>, 'pending'>,

View File

@ -13,7 +13,7 @@ const constants: Object = Object.freeze({
TREZOR_CONNECT_ROOT: path.join(ABSOLUTE_BASE, '../trezor-connect/'), TREZOR_CONNECT_ROOT: path.join(ABSOLUTE_BASE, '../trezor-connect/'),
}); });
export const TREZOR_CONNECT_ROOT: string = constants.TREZOR_CONNECT_ROOT; export const { TREZOR_CONNECT_ROOT }: { TREZOR_CONNECT_ROOT: string } = constants;
export const TREZOR_CONNECT: string = path.join(constants.TREZOR_CONNECT_ROOT, 'src/js/index'); export const TREZOR_CONNECT: string = path.join(constants.TREZOR_CONNECT_ROOT, 'src/js/index');
export const TREZOR_IFRAME: string = path.join(constants.TREZOR_CONNECT_ROOT, 'src/js/iframe/iframe.js'); export const TREZOR_IFRAME: string = path.join(constants.TREZOR_CONNECT_ROOT, 'src/js/iframe/iframe.js');
export const TREZOR_POPUP: string = path.join(constants.TREZOR_CONNECT_ROOT, 'src/js/popup/popup.js'); export const TREZOR_POPUP: string = path.join(constants.TREZOR_CONNECT_ROOT, 'src/js/popup/popup.js');
@ -21,10 +21,16 @@ export const TREZOR_WEBUSB: string = path.join(constants.TREZOR_CONNECT_ROOT, 's
export const TREZOR_CONNECT_HTML: string = path.join(constants.TREZOR_CONNECT_ROOT, 'src/html/'); export const TREZOR_CONNECT_HTML: string = path.join(constants.TREZOR_CONNECT_ROOT, 'src/html/');
export const TREZOR_CONNECT_FILES: string = path.join(constants.TREZOR_CONNECT_ROOT, 'src/data/'); export const TREZOR_CONNECT_FILES: string = path.join(constants.TREZOR_CONNECT_ROOT, 'src/data/');
export const BUILD: string = constants.BUILD; export const {
export const SRC: string = constants.SRC; BUILD,
export const PORT: string = constants.PORT; SRC,
export const INDEX: string = constants.INDEX; PORT,
export const PUBLIC: string = constants.PUBLIC; INDEX,
PUBLIC,
}: { BUILD: string, SRC: string, PORT: string, INDEX: string, PUBLIC: string } = constants;
// export const SRC: string = constants.SRC;
// export const PORT: string = constants.PORT;
// export const INDEX: string = constants.INDEX;
// export const PUBLIC: string = constants.PUBLIC;
export default constants; export default constants;