Merge branch 'master' into fix-menu-underline

pull/15/head
Szymon Lesisz 6 years ago committed by GitHub
commit 397b757d1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,54 @@
TREZOR REFERENCE SOURCE LICENSE (T-RSL)
=======================================
This license governs use of the accompanying software. If you use the software,
you accept this license. If you do not accept the license, do not use the
software.
1. Definitions
--------------
The terms "reproduce," "reproduction" and "distribution" have the same meaning
here as under U.S. copyright law.
"You" means the licensee of the software.
"Your company" means the company you worked for when you downloaded the
software.
"Reference use" means use of the software within your company as a reference,
in read only form, for the sole purposes of debugging your products,
maintaining your products, or enhancing the interoperability of your products
with the software, and specifically excludes the right to distribute the
software outside of your company.
"Licensed patents" means any Licensor patent claims which read directly on the
software as distributed by the Licensor under this license.
2. Grant of Rights
------------------
(A) Copyright Grant - Subject to the terms of this license, the Licensor grants
you a non-transferable, non-exclusive, worldwide, royalty-free copyright
license to reproduce the software for reference use.
(B) Patent Grant - Subject to the terms of this license, the Licensor grants
you a non-transferable, non-exclusive, worldwide, royalty-free patent license
under licensed patents for reference use.
3. Limitations
--------------
(A) No Trademark License - This license does not grant you any rights to use
the Licensor's name, logo, or trademarks.
(B) If you begin patent litigation against the Licensor over patents that you
think may apply to the software (including a cross-claim or counterclaim in
a lawsuit), your license to the software ends automatically.
(C) The software is licensed "as-is." You bear the risk of using it. The
Licensor gives no express warranties, guarantees or conditions. You may have
additional consumer rights under your local laws which this license cannot
change. To the extent permitted under your local laws, the Licensor excludes
the implied warranties of merchantability, fitness for a particular purpose and
non-infringement.

@ -5,37 +5,29 @@ import EthereumjsUtil from 'ethereumjs-util';
import EthereumjsUnits from 'ethereumjs-units';
import EthereumjsTx from 'ethereumjs-tx';
import TrezorConnect from 'trezor-connect';
import { push } from 'react-router-redux';
import BigNumber from 'bignumber.js';
import { strip } from 'utils/ethUtils';
import * as NOTIFICATION from 'actions/constants/notification';
import * as SEND from 'actions/constants/send';
import { initialState } from 'reducers/SendFormReducer';
import { findAccount } from 'reducers/AccountsReducer';
import { findToken } from 'reducers/TokensReducer';
import { findDevice } from 'reducers/utils';
import * as stateUtils from 'reducers/utils';
import { findDevice, getPendingAmount, getPendingNonce } from 'reducers/utils';
import type {
PendingTx,
Dispatch,
GetState,
Action,
ThunkAction,
AsyncAction,
RouterLocationState,
TrezorDevice,
} from 'flowtype';
import type { State as AccountState } from 'reducers/SelectedAccountReducer';
import type { Web3Instance } from 'reducers/Web3Reducer';
import type { Config, Coin } from 'reducers/LocalStorageReducer';
import type { Coin } from 'reducers/LocalStorageReducer';
import type { Token } from 'reducers/TokensReducer';
import type { State, FeeLevel } from 'reducers/SendFormReducer';
import type { Account } from 'reducers/AccountsReducer';
import type { Props } from 'views/Wallet/views/AccountSend/Container';
import * as SessionStorageActions from './SessionStorageActions';
import { estimateGas, getGasPrice, pushTx } from './Web3Actions';
import { estimateGas, pushTx } from './Web3Actions';
export type SendTxAction = {
type: typeof SEND.TX_COMPLETE,
@ -155,7 +147,6 @@ export const calculate = (prevProps: Props, props: Props) => {
} = props.selectedAccount;
if (!account) return;
const prevState = prevProps.sendForm;
const state = props.sendForm;
const isToken: boolean = state.currency !== state.networkSymbol;
@ -169,7 +160,7 @@ export const calculate = (prevProps: Props, props: Props) => {
if (state.setMax) {
const pendingAmount: BigNumber = stateUtils.getPendingAmount(pending, state.currency, isToken);
const pendingAmount: BigNumber = getPendingAmount(pending, state.currency, isToken);
if (isToken) {
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,
});
@ -286,7 +277,6 @@ const addressValidation = (): ThunkAction => (dispatch: Dispatch, getState: GetS
const {
account,
network,
tokens,
} = getState().selectedAccount;
if (!account || !network) return;
@ -310,7 +300,7 @@ const addressValidation = (): ThunkAction => (dispatch: Dispatch, getState: GetS
} else {
const otherNetworkAccount = savedAccounts[0];
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);
if (device && otherNetwork) {
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;
// valid address
if (state.touched.address) {
if (state.address.length < 1) {
/* if (state.address.length < 1) {
errors.address = 'Address is not set';
} else if (!EthereumjsUtil.isValidAddress(state.address)) {
errors.address = 'Address is not valid';
@ -363,6 +353,20 @@ export const validation = (props: Props): void => {
} else if (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';
} else {
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) {
const token = findToken(tokens, account.address, state.currency, account.deviceState);
@ -612,7 +616,7 @@ export const updateFeeLevels = (): ThunkAction => (dispatch: Dispatch, getState:
// update only gasPrice
currentState.selectedFeeLevel.gasPrice = currentState.recommendedGasPrice;
// leave gas limit as it was
gasLimit = currentState.gasLimit;
({ gasLimit } = currentState);
}
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 isToken: boolean = currentState.currency !== currentState.networkSymbol;
const touched = { ...currentState.touched };
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 {
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> => {
const {
account,
@ -806,7 +808,7 @@ export const onSend = (): AsyncAction => async (dispatch: Dispatch, getState: Ge
txAddress = token.address;
}
const pendingNonce: number = stateUtils.getPendingNonce(pending);
const pendingNonce: number = getPendingNonce(pending);
const nonce = pendingNonce > 0 && pendingNonce >= account.nonce ? pendingNonce : account.nonce;
console.warn('NONCE', nonce, account.nonce, pendingNonce);

@ -1,17 +1,11 @@
/* @flow */
import EthereumjsUtil from 'ethereumjs-util';
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 type {
ThunkAction, AsyncAction, Action, GetState, Dispatch,
ThunkAction, Action, Dispatch,
} from 'flowtype';
import type { State } from 'reducers/SummaryReducer';
import type { Token } from 'reducers/TokensReducer';
export type SummaryAction = {
type: typeof SUMMARY.INIT,
@ -22,7 +16,7 @@ export type SummaryAction = {
type: typeof SUMMARY.DETAILS_TOGGLE
}
export const init = (): ThunkAction => (dispatch: Dispatch, getState: GetState): void => {
export const init = (): ThunkAction => (dispatch: Dispatch): void => {
const state: State = {
...initialState,
};

@ -25,10 +25,6 @@ export type TokenAction = {
payload: State
}
type SelectOptions = {
options?: Array<NetworkToken>
}
// action from component <reactSelect>
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);
};
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> => {
const web3instance = getState().web3.find(w3 => w3.network === account.network);
if (!web3instance) return;
@ -82,20 +92,6 @@ export const add = (token: NetworkToken, account: Account): AsyncAction => async
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 => ({
type: TOKEN.REMOVE,
token,

@ -1,10 +1,7 @@
/* @flow */
import TrezorConnect, {
UI, DEVICE, DEVICE_EVENT, UI_EVENT, TRANSPORT_EVENT,
DEVICE, DEVICE_EVENT, UI_EVENT, TRANSPORT_EVENT,
} from 'trezor-connect';
import * as TOKEN from 'actions/constants/token';
import * as CONNECT from 'actions/constants/TrezorConnect';
import * as NOTIFICATION from 'actions/constants/notification';
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> => {
// set listeners
TrezorConnect.on(DEVICE_EVENT, (event: DeviceMessage): void => {
@ -112,7 +116,7 @@ export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetS
});
// $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 = 'https://sisyfos.trezor.io/connect/';
// 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
// after device_connect event
// 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> => {
const { devices } = getState();
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) {
const devUrl: string = `${device.features.device_id}${device.instance ? `:${device.instance}` : ''}`;
dispatch(push(`/device/${devUrl}/settings`));

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

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

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

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

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

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

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

@ -63,12 +63,12 @@ const ErrorMessage = styled.div`
`;
export default class DuplicateDevice extends Component<Props, State> {
keyboardHandler: (event: KeyboardEvent) => void;
state: State;
input: ?HTMLInputElement;
keyboardHandler: (event: KeyboardEvent) => void;
constructor(props: 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 {
// one time autofocus
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() {
if (!this.props.modal.opened) return;
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;
const { device } = this.props.modal;
const { onCancel, onDuplicateDevice } = this.props.modalActions;
const { onCancel } = this.props.modalActions;
const {
defaultName,
instanceName,

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

@ -9,8 +9,8 @@ import { CSSTransition } from 'react-transition-group';
import { UI } from 'trezor-connect';
import { default as ModalActions } from 'actions/ModalActions';
import { default as ReceiveActions } from 'actions/ReceiveActions';
import ModalActions from 'actions/ModalActions';
import ReceiveActions from 'actions/ReceiveActions';
import * as RECEIVE from 'actions/constants/receive';
import * as CONNECT from 'actions/constants/TrezorConnect';
@ -51,8 +51,6 @@ type DispatchProps = {
export type Props = StateProps & DispatchProps;
const duration = 300;
const Fade = ({ children, ...props }) => (
<CSSTransition
{...props}
@ -75,7 +73,7 @@ const ModalContainer = styled.div`
flex-direction: column;
align-items: center;
overflow: auto;
padding: 20px;
padding: 20px;
`;
const ModalWindow = styled.div`
@ -125,7 +123,8 @@ class Modal extends Component<Props> {
component = (<DuplicateDevice {...this.props} />);
break;
default: null;
default:
component = 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,
accounts: state.accounts,
devices: state.devices,

@ -4,14 +4,13 @@ import raf from 'raf';
import colors from 'config/colors';
import P from 'components/Paragraph';
import { FONT_SIZE } from 'config/variables';
import { H2 } from 'components/Heading';
import Link from 'components/Link';
import Checkbox from 'components/Checkbox';
import Button from 'components/Button';
import Input from 'components/inputs/Input';
import styled from 'styled-components';
import type { Props } from './index';
import type { Props } from '../../index';
const Wrapper = styled.div`
padding: 24px 48px;
@ -55,14 +54,6 @@ type State = {
}
export default class PinModal extends Component<Props, State> {
keyboardHandler: (event: KeyboardEvent) => void;
state: State;
passphraseInput: ?HTMLInputElement;
passphraseRevisionInput: ?HTMLInputElement;
constructor(props: 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 {
if (event.keyCode === 13) {
event.preventDefault();
@ -108,6 +108,7 @@ export default class PinModal extends Component<Props, State> {
}
}
componentDidMount(): void {
// one time autofocus
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,
// so we need to replace it thru javascript
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 => {
// https://codepen.io/MiDri/pen/PGqvrO
// or
// https://github.com/zakangelle/react-password-mask/blob/master/src/index.js
if (input === 'passphrase') {
this.setState({
match: this.state.singleInput || this.state.passphraseRevision === value,
this.setState(previousState => ({
match: previousState.singleInput || previousState.passphraseRevision === value,
passphrase: value,
});
}));
} else {
this.setState({
match: this.state.passphrase === value,
this.setState(previousState => ({
match: previousState.passphrase === value,
passphraseRevision: value,
passphraseRevisionTouched: true,
});
}));
}
}

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

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

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

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

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

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

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

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

@ -17,7 +17,7 @@ export const getSelectedDevice = (state: State): ?TrezorDevice => {
const locationState = state.router.location.state;
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) => {
if (!d.features && d.path === locationState.device) {
return true;
@ -64,14 +64,14 @@ export const getSelectedAccount = (state: State): ?Account => {
const locationState = state.router.location.state;
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);
};
export const getSelectedNetwork = (state: State): ?Coin => {
const device = state.wallet.selectedDevice;
const coins = state.localStorage.config.coins;
const { coins } = state.localStorage.config;
const locationState = state.router.location.state;
if (!device || !locationState.network) return null;

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

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

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

@ -1,8 +1,5 @@
/* @flow */
import { DEVICE } from 'trezor-connect';
import { LOCATION_CHANGE, push, replace } from 'react-router-redux';
import { LOCATION_CHANGE/* , replace */ } from 'react-router-redux';
import * as CONNECT from 'actions/constants/TrezorConnect';
import * as WALLET from 'actions/constants/wallet';
import * as NotificationActions from 'actions/NotificationActions';
@ -11,12 +8,7 @@ import type {
Middleware,
MiddlewareAPI,
MiddlewareDispatch,
State,
Dispatch,
Action,
ThunkAction,
AsyncAction,
GetState,
RouterLocationState,
TrezorDevice,
} from 'flowtype';
@ -51,7 +43,7 @@ const validation = (api: MiddlewareAPI, params: RouterLocationState): boolean =>
let device: ?TrezorDevice;
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 {
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')) {
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 (!params.account) return false;
}
if (params.account) {
// if (params.account) {
}
// }
return true;
};
let __unloading: boolean = false;
const LandingURLS: Array<string> = [
'/',
'/bridge',
];
const RouterService: Middleware = (api: MiddlewareAPI) => (next: MiddlewareDispatch) => (action: Action): Action => {
if (action.type === WALLET.ON_BEFORE_UNLOAD) {
__unloading = true;

@ -1,10 +1,8 @@
/* @flow */
import { push } from 'react-router-redux';
import TrezorConnect, {
TRANSPORT, DEVICE_EVENT, UI_EVENT, UI, DEVICE,
import {
TRANSPORT, DEVICE,
} from 'trezor-connect';
import * as TrezorConnectActions from 'actions/TrezorConnectActions';
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 STORAGE from 'actions/constants/localStorage';
import * as CONNECT from 'actions/constants/TrezorConnect';
import * as NOTIFICATION from 'actions/constants/notification';
import * as MODAL from 'actions/constants/modal';
import type {
Middleware,
MiddlewareAPI,
MiddlewareDispatch,
State,
Dispatch,
Action,
AsyncAction,
GetState,
RouterLocationState,
} from 'flowtype';
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 prevRouterState: $ElementType<State, 'router'> = api.getState().router;
// const prevRouterState: $ElementType<State, 'router'> = api.getState().router;
next(action);

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

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

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

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

@ -1,7 +1,4 @@
/* @flow */
import React from 'react';
import { bindActionCreators } from 'redux';
import { connect } 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,
});
const mapDispatchToProps: MapDispatchToProps<Dispatch, OwnProps, DispatchProps> = (dispatch: Dispatch): DispatchProps => ({
const mapDispatchToProps: MapDispatchToProps<Dispatch, OwnProps, DispatchProps> = (/* dispatch: Dispatch */): DispatchProps => ({
});

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

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

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

@ -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,
accounts: state.accounts,
router: state.router,

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

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

@ -3,7 +3,6 @@ import React, { Component } from 'react';
import styled from 'styled-components';
import TrezorConnect from 'trezor-connect';
import type { TrezorDevice } from 'flowtype';
import DeviceHeader from 'components/DeviceHeader';
import Button from 'components/Button';
import { isWebUSB } from 'utils/device';
import MenuItems from './components/MenuItems';
@ -39,6 +38,13 @@ class DeviceMenu extends Component<Props> {
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() {
const { transport } = this.props.connect;
if (isWebUSB(transport)) TrezorConnect.renderWebUSBButton();
@ -61,17 +67,10 @@ class DeviceMenu extends Component<Props> {
}
}
blurHandler(event: FocusEvent): void {
blurHandler(): void {
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 {
if (item.type === 'reload') {
this.props.acquireDevice();

@ -17,11 +17,26 @@ type Props = {
const AsideWrapper = styled.aside`
position: relative;
top: 0;
width: 320px;
min-width: 320px;
overflow-x: hidden;
overflow: hidden;
background: ${colors.MAIN};
border-right: 1px solid ${colors.DIVIDER};
.fixed {
position: fixed;
border-right: 1px solid ${colors.DIVIDER};
}
.fixed-bottom {
padding-bottom: 60px;
.sticky-bottom {
position: fixed;
bottom: 0;
background: ${colors.MAIN};
border-right: 1px solid ${colors.DIVIDER};
}
}
`;
const StickyContainerWrapper = styled.div`

@ -2,6 +2,7 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import colors from 'config/colors';
import Icon from 'components/Icon';
import Sticky from 'react-sticky-el';
import icons from 'config/icons';
import { TransitionGroup, CSSTransition } from 'react-transition-group';
import styled from 'styled-components';
@ -11,6 +12,8 @@ import CoinMenu from './components/CoinMenu';
import DeviceMenu from './components/DeviceMenu';
import StickyContainer from './components/StickyContainer';
const Header = styled(DeviceHeader)``;
const TransitionGroupWrapper = styled(TransitionGroup)`
width: 640px;
`;
@ -21,14 +24,15 @@ const TransitionContentWrapper = styled.div`
vertical-align: top;
`;
const StickyBottom = styled.div`
const Footer = styled.div`
position: fixed;
bottom: 0;
background: ${colors.MAIN};
border-right: 1px solid ${colors.DIVIDER};
`;
const MenuWrapper = styled.div`
const Body = styled.div`
overflow: auto;
background: ${colors.LANDING};
`;
@ -40,11 +44,6 @@ const Help = styled.div`
width: 319px;
padding: 8px 0px;
border-top: 1px solid ${colors.DIVIDER};
&.fixed {
position: fixed;
bottom: 0px;
}
`;
const A = styled.a`
@ -150,28 +149,25 @@ class LeftNavigation extends Component {
}
render() {
const { selectedDevice } = this.props.wallet;
return (
<StickyContainer
location={this.props.location.pathname}
deviceSelection={this.props.deviceDropdownOpened}
>
{selectedDevice && (
<DeviceHeader
onClickWrapper={() => this.handleOpen()}
device={this.props.wallet.selectedDevice}
transport={this.props.connect.transport}
devices={this.props.devices}
isOpen={this.props.deviceDropdownOpened}
{...this.props}
/>
) }
<MenuWrapper>
<Header
onClickWrapper={() => this.handleOpen()}
device={this.props.wallet.selectedDevice}
transport={this.props.connect.transport}
devices={this.props.devices}
isOpen={this.props.deviceDropdownOpened}
{...this.props}
/>
<Body>
{this.state.shouldRenderDeviceSelection && <DeviceMenu {...this.props} />}
{this.shouldRenderAccounts() && this.getMenuTransition(<AccountMenu {...this.props} />)}
{this.shouldRenderCoins() && this.getMenuTransition(<CoinMenu {...this.props} />)}
</MenuWrapper>
<StickyBottom>
</Body>
<Footer className="sticky-bottom">
<Help>
<A
href="https://trezor.io/support/"
@ -181,7 +177,8 @@ class LeftNavigation extends Component {
<Icon size={26} icon={icons.CHAT} color={colors.TEXT_SECONDARY} />Need help?
</A>
</Help>
</StickyBottom>
</Footer>
<Sticky />
</StickyContainer>
);
}

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

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

@ -20,13 +20,13 @@ import TopNavigationAccount from './components/TopNavigationAccount';
import TopNavigationDeviceSettings from './components/TopNavigationDeviceSettings';
type WalletContainerProps = {
wallet: $ElementType<State, 'wallet'>,
// wallet: $ElementType<State, 'wallet'>,
children?: React.Node
}
type ContentProps = {
children?: React.Node
}
// type ContentProps = {
// children?: React.Node
// }
const AppWrapper = styled.div`
position: relative;
@ -83,7 +83,7 @@ const Wallet = (props: WalletContainerProps) => (
<AppWrapper>
<Header />
<WalletWrapper>
<LeftNavigation />
{props.wallet.selectedDevice && <LeftNavigation />}
<MainContent>
<Navigation>
<Route path="/device/:device/network/:network/account/:account" component={TopNavigationAccount} />
@ -101,7 +101,7 @@ const Wallet = (props: WalletContainerProps) => (
</AppWrapper>
);
const mapStateToProps: MapStateToProps<State, {}, WalletContainerProps> = (state: State, own: {}): WalletContainerProps => ({
const mapStateToProps: MapStateToProps<State, {}, WalletContainerProps> = (state: State): WalletContainerProps => ({
wallet: state.wallet,
});

@ -24,7 +24,7 @@ type 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',
selectedAccount: state.selectedAccount,
wallet: state.wallet,

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

@ -5,7 +5,7 @@ import * as React from 'react';
import { bindActionCreators } from '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 type { MapStateToProps, MapDispatchToProps } from 'react-redux';
import type { State, Dispatch } from 'flowtype';
@ -29,7 +29,7 @@ export type 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',
selectedAccount: state.selectedAccount,
wallet: state.wallet,

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

@ -13,7 +13,7 @@ const constants: Object = Object.freeze({
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_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');
@ -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_FILES: string = path.join(constants.TREZOR_CONNECT_ROOT, 'src/data/');
export const BUILD: string = constants.BUILD;
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 const {
BUILD,
SRC,
PORT,
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;
Loading…
Cancel
Save