1
0
mirror of https://github.com/trezor/trezor-wallet synced 2024-11-15 21:08:57 +00:00

Merge pull request #3 from satoshilabs/styled-components-refactor

Styled components upgrade and fixes [WIP]
This commit is contained in:
Szymon Lesisz 2018-08-20 13:03:48 +02:00 committed by GitHub
commit 11eb56433e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
147 changed files with 3677 additions and 1728 deletions

View File

@ -7,6 +7,7 @@
"react"
],
"plugins": [
"react-hot-loader/babel",
"transform-class-properties",
"transform-object-rest-spread",
"transform-flow-strip-types",
@ -14,9 +15,19 @@
"polyfill": false,
"regenerator": true
}],
["babel-plugin-root-import", {
"rootPathSuffix": "./src",
"rootPathPrefix": "~"
["module-resolver", {
"root": ["./src"],
"alias": {
"config": "./src/js/config",
"constants": "./src/js/constants",
"components": "./src/js/components",
"actions": "./src/js/actions",
"reducers": "./src/js/reducers",
"support": "./src/js/support",
"utils": "./src/js/utils",
"services": "./src/js/services",
"views": "./src/js/views"
}
}],
"babel-plugin-styled-components"
],

View File

@ -3,13 +3,16 @@
"eslint-config-airbnb",
"plugin:flowtype/recommended",
"plugin:jest/recommended"
],
"env": {
"browser": true,
"jest": true
},
"rules": {
"class-methods-use-this": 0,
"react/require-default-props": 0,
"react/forbid-prop-types": 0,
"react/destructuring-assignment": 0,
"react/jsx-one-expression-per-line": 0,
"react/jsx-indent": [2, 4],
"react/jsx-indent-props": [2, 4],
@ -25,21 +28,15 @@
"spaced-comment": 0
},
"plugins": [
"react",
"import",
"react",
"jest",
"flowtype"
],
"settings": {
"import/parser": "babel-eslint",
"import/resolver": {
"node": {
"moduleDirectory": [
"src",
"node_modules"
]
}
},
"babel-module": {}
},
"import/ignore": [
"\\.(scss|less|css)$"
]

View File

@ -30,4 +30,14 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowIssue
esproposal.decorators=ignore
module.name_mapper='.*\(.less\)' -> 'CSSModule'
module.name_mapper='^\(~/\)' -> '<PROJECT_ROOT>/src/'
module.name_mapper='^universal' -> '<PROJECT_ROOT>/src/'
module.name_mapper='^config' -> '<PROJECT_ROOT>/src/js/config'
module.name_mapper='^constants' -> '<PROJECT_ROOT>/src/js/constants'
module.name_mapper='^components' -> '<PROJECT_ROOT>/src/js/components'
module.name_mapper='^actions' -> '<PROJECT_ROOT>/src/js/actions'
module.name_mapper='^reducers' -> '<PROJECT_ROOT>/src/js/reducers'
module.name_mapper='^support' -> '<PROJECT_ROOT>/src/js/support'
module.name_mapper='^utils' -> '<PROJECT_ROOT>/src/js/utils'
module.name_mapper='^services' -> '<PROJECT_ROOT>/src/js/services'
module.name_mapper='^views' -> '<PROJECT_ROOT>/src/js/views'
module.system=haste

13
.stylelintrc Normal file
View File

@ -0,0 +1,13 @@
{
"processors": [
"stylelint-processor-styled-components"
],
"extends": [
"stylelint-config-recommended",
"stylelint-config-styled-components"
],
"rules": {
"indentation": 4,
"block-no-empty": null
}
}

17
jsconfig.json Normal file
View File

@ -0,0 +1,17 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"*": ["src/*"],
"components/*": ["./src/js/components/*"],
"config/*": ["./src/js/config/*"],
"constants/*": ["./src/js/constants/*"],
"support/*": ["./src/js/support/*"],
"actions/*": ["./src/js/actions/*"],
"reducers/*": ["./src/js/reducers/*"],
"utils/*": ["./src/js/utils/*"],
"services/*": ["./src/js/services/*"],
"views/*": ["./src/js/views/*"],
}
}
}

View File

@ -19,21 +19,26 @@
"dev:local": "webpack-dev-server --config ./webpack/config.dev.local.babel.js --mode development",
"build": "rm -rf build && webpack --config ./webpack/config.prod.babel.js --progress",
"flow": "flow check src/js",
"lint": "npx eslint ./src ./webpack",
"test-unit": "jest",
"test-unit:watch": "jest -o --watch"
"lint": "run-s lint:*",
"lint:js": "eslint ./src/js ./webpack",
"lint:css": "stylelint './src/js/**/*.js'",
"test:*": "run-s test:*",
"test:unit": "jest",
"test-unit:watch": "jest -o --watchAll"
},
"dependencies": {
"babel": "^6.23.0",
"babel-core": "^6.26.3",
"color-hash": "^1.0.3",
"copy-webpack-plugin": "^4.5.2",
"date-fns": "^1.29.0",
"ethereumjs-tx": "^1.3.3",
"ethereumjs-units": "^0.2.0",
"ethereumjs-util": "^5.1.4",
"hdkey": "^0.8.0",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.4.1",
"npm-run-all": "^4.1.3",
"prop-types": "^15.6.2",
"raf": "^3.4.0",
"raven-js": "^3.22.3",
@ -41,7 +46,7 @@
"react": "^16.2.0",
"react-css-transition": "^0.7.4",
"react-dom": "^16.2.0",
"react-hot-loader": "4.2.0",
"react-hot-loader": "^4.3.4",
"react-qr-svg": "^2.1.0",
"react-redux": "^5.0.7",
"react-router-dom": "^4.2.2",
@ -54,6 +59,7 @@
"redux-raven-middleware": "^1.2.0",
"redux-thunk": "^2.2.0",
"styled-components": "^3.3.3",
"styled-normalize": "^8.0.0",
"trezor-connect": "5.0.30",
"web3": "^0.19.0",
"webpack": "^4.16.3",
@ -64,7 +70,7 @@
"babel-cli": "^6.24.1",
"babel-eslint": "^8.2.6",
"babel-loader": "^7.1.5",
"babel-plugin-root-import": "^6.1.0",
"babel-plugin-module-resolver": "^3.1.1",
"babel-plugin-styled-components": "^1.5.1",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-flow-strip-types": "^6.22.0",
@ -76,8 +82,9 @@
"css-loader": "0.28.11",
"eslint": "^4",
"eslint-config-airbnb": "^17.0.0",
"eslint-import-resolver-babel-module": "^4.0.0",
"eslint-plugin-flowtype": "^2.50.0",
"eslint-plugin-import": "^2.13.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jest": "^21.18.0",
"eslint-plugin-jsx-a11y": "^6.1.1",
"eslint-plugin-react": "^7.10.0",
@ -86,6 +93,10 @@
"jest": "^23.4.2",
"less": "^3.0.1",
"less-loader": "4.1.0",
"stylelint": "^9.4.0",
"stylelint-config-standard": "^18.2.0",
"stylelint-config-styled-components": "^0.1.1",
"stylelint-processor-styled-components": "^1.3.2",
"webpack-cli": "^2.1.3",
"webpack-dev-server": "^3.1.4",
"yargs": "11.0.0"

View File

@ -11,25 +11,25 @@ import type {
PlainDispatch as ReduxPlainDispatch,
} from 'redux';
import type { Reducers, ReducersState } from '~/js/reducers';
import type { Reducers, ReducersState } from 'reducers';
// Actions
import type { SelectedAccountAction } from '~/js/actions/SelectedAccountActions';
import type { AccountAction } from '~/js/actions/AccountsActions';
import type { DiscoveryAction } from '~/js/actions/DiscoveryActions';
import type { StorageAction } from '~/js/actions/LocalStorageActions';
import type { LogAction } from '~/js/actions/LogActions';
import type { ModalAction } from '~/js/actions/ModalActions';
import type { NotificationAction } from '~/js/actions/NotificationActions';
import type { PendingTxAction } from '~/js/actions/PendingTxActions';
import type { ReceiveAction } from '~/js/actions/ReceiveActions';
import type { SendFormAction } from '~/js/actions/SendFormActions';
import type { SummaryAction } from '~/js/actions/SummaryActions';
import type { TokenAction } from '~/js/actions/TokenActions';
import type { TrezorConnectAction } from '~/js/actions/TrezorConnectActions';
import type { WalletAction } from '~/js/actions/WalletActions';
import type { Web3Action } from '~/js/actions/Web3Actions';
import type { FiatRateAction } from '~/js/services/CoinmarketcapService'; // this service has no action file, all is written inside one file
import type { SelectedAccountAction } from 'actions/SelectedAccountActions';
import type { AccountAction } from 'actions/AccountsActions';
import type { DiscoveryAction } from 'actions/DiscoveryActions';
import type { StorageAction } from 'actions/LocalStorageActions';
import type { LogAction } from 'actions/LogActions';
import type { ModalAction } from 'actions/ModalActions';
import type { NotificationAction } from 'actions/NotificationActions';
import type { PendingTxAction } from 'actions/PendingTxActions';
import type { ReceiveAction } from 'actions/ReceiveActions';
import type { SendFormAction } from 'actions/SendFormActions';
import type { SummaryAction } from 'actions/SummaryActions';
import type { TokenAction } from 'actions/TokenActions';
import type { TrezorConnectAction } from 'actions/TrezorConnectActions';
import type { WalletAction } from 'actions/WalletActions';
import type { Web3Action } from 'actions/Web3Actions';
import type { FiatRateAction } from 'services/CoinmarketcapService'; // this service has no action file, all is written inside one file
import type {
Device,
@ -68,7 +68,7 @@ export type UnknownDevice = $Exact<{
+label: string,
+features: null,
state: ?string,
remember: boolean; // device should be remembered
connected: boolean; // device is connected
available: boolean; // device cannot be used because of features.passphrase_protection is different then expected
@ -136,12 +136,12 @@ export type Action =
export type State = ReducersState;
// reexport reduces types
export type { Coin } from '~/js/reducers/LocalStorageReducer';
export type { Account } from '~/js/reducers/AccountsReducer';
export type { Discovery } from '~/js/reducers/DiscoveryReducer';
export type { Token } from '~/js/reducers/TokensReducer';
export type { Web3Instance } from '~/js/reducers/Web3Reducer';
export type { PendingTx } from '~/js/reducers/PendingTxReducer';
export type { Coin } from 'reducers/LocalStorageReducer';
export type { Account } from 'reducers/AccountsReducer';
export type { Discovery } from 'reducers/DiscoveryReducer';
export type { Token } from 'reducers/TokensReducer';
export type { Web3Instance } from 'reducers/Web3Reducer';
export type { PendingTx } from 'reducers/PendingTxReducer';
export type Accounts = $ElementType<State, 'accounts'>;
export type LocalStorage = $ElementType<State, 'localStorage'>;

View File

@ -1,8 +1,8 @@
/* @flow */
import * as ACCOUNT from './constants/account';
import type { Action, TrezorDevice } from '~/flowtype';
import type { State } from '../reducers/AccountsReducer';
import * as ACCOUNT from 'actions/constants/account';
import type { Action, TrezorDevice } from 'flowtype';
import type { State } from 'reducers/AccountsReducer';
export type AccountAction =
AccountFromStorageAction

View File

@ -3,20 +3,19 @@
import TrezorConnect from 'trezor-connect';
import HDKey from 'hdkey';
import EthereumjsUtil from 'ethereumjs-util';
import * as DISCOVERY from './constants/discovery';
import * as ACCOUNT from './constants/account';
import * as TOKEN from './constants/token';
import * as NOTIFICATION from './constants/notification';
import * as DISCOVERY from 'actions/constants/discovery';
import * as ACCOUNT from 'actions/constants/account';
import * as TOKEN from 'actions/constants/token';
import * as NOTIFICATION from 'actions/constants/notification';
import type {
ThunkAction, AsyncAction, Action, GetState, Dispatch, TrezorDevice,
} from 'flowtype';
import type { Discovery, State } from 'reducers/DiscoveryReducer';
import * as AccountsActions from './AccountsActions';
import { getNonceAsync, getBalanceAsync, getTokenBalanceAsync } from './Web3Actions';
import { setBalance as setTokenBalance } from './TokenActions';
import type {
ThunkAction, AsyncAction, Action, GetState, Dispatch, TrezorDevice,
} from '~/flowtype';
import type { Discovery, State } from '../reducers/DiscoveryReducer';
export type DiscoveryAction = {
type: typeof DISCOVERY.FROM_STORAGE,

View File

@ -1,21 +1,21 @@
/* @flow */
import * as CONNECT from './constants/TrezorConnect';
import * as ACCOUNT from './constants/account';
import * as TOKEN from './constants/token';
import * as DISCOVERY from './constants/discovery';
import * as STORAGE from './constants/localStorage';
import * as PENDING from './constants/pendingTx';
import { JSONRequest, httpRequest } from '../utils/networkUtils';
import * as CONNECT from 'actions/constants/TrezorConnect';
import * as ACCOUNT from 'actions/constants/account';
import * as TOKEN from 'actions/constants/token';
import * as DISCOVERY from 'actions/constants/discovery';
import * as STORAGE from 'actions/constants/localStorage';
import * as PENDING from 'actions/constants/pendingTx';
import { JSONRequest, httpRequest } from 'utils/networkUtils';
import type {
ThunkAction, AsyncAction, GetState, Dispatch, TrezorDevice,
} from '~/flowtype';
import type { Config, Coin, TokensCollection } from '../reducers/LocalStorageReducer';
} from 'flowtype';
import type { Config, Coin, TokensCollection } from 'reducers/LocalStorageReducer';
import AppConfigJSON from '~/data/appConfig.json';
import Erc20AbiJSON from '~/data/ERC20Abi.json';
import AppConfigJSON from 'data/appConfig.json';
import Erc20AbiJSON from 'data/ERC20Abi.json';
export type StorageAction = {
type: typeof STORAGE.READY,

View File

@ -1,12 +1,12 @@
/* @flow */
import * as LOG from './constants/log';
import * as LOG from 'actions/constants/log';
import type {
Action, ThunkAction, GetState, Dispatch,
} from '~/flowtype';
import type { LogEntry } from '../reducers/LogReducer';
} from 'flowtype';
import type { LogEntry } from 'reducers/LogReducer';
export type LogAction = {
type: typeof LOG.OPEN,

View File

@ -2,13 +2,13 @@
import TrezorConnect, { UI, UI_EVENT } from 'trezor-connect';
import * as MODAL from './constants/modal';
import * as CONNECT from './constants/TrezorConnect';
import * as MODAL from 'actions/constants/modal';
import * as CONNECT from 'actions/constants/TrezorConnect';
import type {
ThunkAction, AsyncAction, Action, GetState, Dispatch, Device, TrezorDevice,
} from '~/flowtype';
import type { State } from '../reducers/ModalReducer';
ThunkAction, AsyncAction, Action, GetState, Dispatch, TrezorDevice,
} from 'flowtype';
import type { State } from 'reducers/ModalReducer';
export type ModalAction = {
type: typeof MODAL.CLOSE

View File

@ -1,12 +1,12 @@
/* @flow */
import * as NOTIFICATION from './constants/notification';
import * as NOTIFICATION from 'actions/constants/notification';
import type {
Action, AsyncAction, GetState, Dispatch, RouterLocationState,
} from '~/flowtype';
import type { CallbackAction } from '../reducers/NotificationReducer';
} from 'flowtype';
import type { CallbackAction } from 'reducers/NotificationReducer';
export type NotificationAction = {
type: typeof NOTIFICATION.ADD,

View File

@ -1,8 +1,8 @@
/* @flow */
import * as PENDING from './constants/pendingTx';
import type { State, PendingTx } from '../reducers/PendingTxReducer';
import * as PENDING from 'actions/constants/pendingTx';
import type { State, PendingTx } from 'reducers/PendingTxReducer';
export type PendingTxAction = {
type: typeof PENDING.FROM_STORAGE,

View File

@ -2,15 +2,15 @@
import TrezorConnect from 'trezor-connect';
import * as RECEIVE from './constants/receive';
import * as NOTIFICATION from './constants/notification';
import * as RECEIVE from 'actions/constants/receive';
import * as NOTIFICATION from 'actions/constants/notification';
import { initialState } from '../reducers/ReceiveReducer';
import type { State } from '../reducers/ReceiveReducer';
import { initialState } from 'reducers/ReceiveReducer';
import type { State } from 'reducers/ReceiveReducer';
import type {
TrezorDevice, ThunkAction, AsyncAction, Action, GetState, Dispatch,
} from '~/flowtype';
} from 'flowtype';
export type ReceiveAction = {
type: typeof RECEIVE.INIT,

View File

@ -2,16 +2,14 @@
import { LOCATION_CHANGE } from 'react-router-redux';
import * as ACCOUNT from './constants/account';
import * as SEND from './constants/send';
import * as NOTIFICATION from './constants/notification';
import * as PENDING from './constants/pendingTx';
import * as ACCOUNT from 'actions/constants/account';
import * as SEND from 'actions/constants/send';
import * as NOTIFICATION from 'actions/constants/notification';
import * as PENDING from 'actions/constants/pendingTx';
import * as SendFormActions from './SendFormActions';
import * as SessionStorageActions from './SessionStorageActions';
import * as stateUtils from '../reducers/utils';
import * as stateUtils from 'reducers/utils';
import { initialState } from '../reducers/SelectedAccountReducer';
import { initialState } from 'reducers/SelectedAccountReducer';
import type {
Coin,
@ -22,7 +20,9 @@ import type {
GetState,
Dispatch,
State,
} from '~/flowtype';
} from 'flowtype';
import * as SessionStorageActions from './SessionStorageActions';
import * as SendFormActions from './SendFormActions';
export type SelectedAccountAction = {

View File

@ -7,17 +7,15 @@ 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 { estimateGas, getGasPrice, pushTx } from './Web3Actions';
import * as SessionStorageActions from './SessionStorageActions';
import * as NOTIFICATION from './constants/notification';
import * as SEND from './constants/send';
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 { 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 type {
PendingTx,
@ -28,14 +26,16 @@ import type {
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 { Token } from '../reducers/TokensReducer';
import type { State, FeeLevel } from '../reducers/SendFormReducer';
import type { Account } from '../reducers/AccountsReducer';
import type { Props } from '../components/wallet/account/send';
} 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 { Token } from 'reducers/TokensReducer';
import type { State, FeeLevel } from 'reducers/SendFormReducer';
import type { Account } from 'reducers/AccountsReducer';
import type { Props } from 'components/wallet/account/send';
import * as SessionStorageActions from './SessionStorageActions';
import { estimateGas, getGasPrice, pushTx } from './Web3Actions';
export type SendTxAction = {
type: typeof SEND.TX_COMPLETE,
@ -837,7 +837,7 @@ export const onSend = (): AsyncAction => async (dispatch: Dispatch, getState: Ge
},
useEmptyPassphrase: !selected.instance,
path: address_n,
transaction: txData
transaction: txData,
});
if (!signedTransaction || !signedTransaction.success) {

View File

@ -1,12 +1,12 @@
/* @flow */
import type { State as SendFormState } from '../reducers/SendFormReducer';
import type { State as SendFormState } from 'reducers/SendFormReducer';
import type {
ThunkAction,
GetState,
Dispatch,
} from '~/flowtype';
} from 'flowtype';
const PREFIX: string = 'trezor:draft-tx:';

View File

@ -2,16 +2,16 @@
import EthereumjsUtil from 'ethereumjs-util';
import * as SUMMARY from './constants/summary';
import * as TOKEN from './constants/token';
import { resolveAfter } from '../utils/promiseUtils';
import { initialState } from '../reducers/SummaryReducer';
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,
} from '~/flowtype';
import type { State } from '../reducers/SummaryReducer';
import type { Token } from '../reducers/TokensReducer';
} from 'flowtype';
import type { State } from 'reducers/SummaryReducer';
import type { Token } from 'reducers/TokensReducer';
export type SummaryAction = {
type: typeof SUMMARY.INIT,

View File

@ -1,15 +1,15 @@
/* @flow */
import * as TOKEN from './constants/token';
import { getTokenInfoAsync, getTokenBalanceAsync } from './Web3Actions';
import * as TOKEN from 'actions/constants/token';
import type {
GetState, AsyncAction, Action, Dispatch,
} from '~/flowtype';
import type { State, Token } from '../reducers/TokensReducer';
import type { Account } from '../reducers/AccountsReducer';
import type { NetworkToken } from '../reducers/LocalStorageReducer';
} from 'flowtype';
import type { State, Token } from 'reducers/TokensReducer';
import type { Account } from 'reducers/AccountsReducer';
import type { NetworkToken } from 'reducers/LocalStorageReducer';
import { getTokenInfoAsync, getTokenBalanceAsync } from './Web3Actions';
export type TokenAction = {
type: typeof TOKEN.FROM_STORAGE,

View File

@ -4,15 +4,13 @@
import TrezorConnect, {
UI, DEVICE, DEVICE_EVENT, UI_EVENT, TRANSPORT_EVENT,
} from 'trezor-connect';
import * as TOKEN from './constants/token';
import * as CONNECT from './constants/TrezorConnect';
import * as NOTIFICATION from './constants/notification';
import * as WALLET from './constants/wallet';
import { getDuplicateInstanceNumber } from '../reducers/utils';
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';
import { getDuplicateInstanceNumber } from 'reducers/utils';
import { push } from 'react-router-redux';
import * as DiscoveryActions from './DiscoveryActions';
import { resolveAfter } from '../utils/promiseUtils';
import type {
@ -33,7 +31,8 @@ import type {
Device,
TrezorDevice,
RouterLocationState,
} from '~/flowtype';
} from 'flowtype';
import * as DiscoveryActions from './DiscoveryActions';
export type TrezorConnectAction = {
@ -209,7 +208,7 @@ export const onSelectDevice = (device: TrezorDevice | Device): ThunkAction => (d
// switch to initial url and reset this value
if (!device.features) {
dispatch(push(`/device/${device.path}/${ device.type === 'unreadable' ? 'unreadable' : 'acquire' }`));
dispatch(push(`/device/${device.path}/${device.type === 'unreadable' ? 'unreadable' : 'acquire'}`));
} else if (device.features.bootloader_mode) {
dispatch(push(`/device/${device.path}/bootloader`));
} else if (!device.features.initialized) {
@ -412,8 +411,8 @@ export const duplicateDevice = (device: TrezorDevice): AsyncAction => async (dis
const extended: Object = { instance };
dispatch({
type: CONNECT.DUPLICATE,
device: { ...device, ...extended }
})
device: { ...device, ...extended },
});
};

View File

@ -2,9 +2,9 @@
import { LOCATION_CHANGE } from 'react-router-redux';
import * as WALLET from './constants/wallet';
import * as CONNECT from './constants/TrezorConnect';
import * as stateUtils from '../reducers/utils';
import * as WALLET from 'actions/constants/wallet';
import * as CONNECT from 'actions/constants/TrezorConnect';
import * as stateUtils from 'reducers/utils';
import type
{
@ -22,7 +22,7 @@ import type
Dispatch,
GetState,
State,
} from '~/flowtype';
} from 'flowtype';
export type WalletAction = {
type: typeof WALLET.SET_INITIAL_URL,
@ -75,8 +75,7 @@ export const toggleDeviceDropdown = (opened: boolean): WalletAction => ({
export const clearUnavailableDevicesData = (prevState: State, device: Device): ThunkAction => (dispatch: Dispatch, getState: GetState): void => {
if (!device.features) return;
const affectedDevices = prevState.devices.filter(d =>
d.features && device.features
const affectedDevices = prevState.devices.filter(d => d.features && device.features
&& d.features.device_id === device.features.device_id
&& d.features.passphrase_protection !== device.features.passphrase_protection);

View File

@ -10,24 +10,24 @@ import TrezorConnect from 'trezor-connect';
import type { ContractFactory, EstimateGasOptions } from 'web3';
import type BigNumber from 'bignumber.js';
import type { TransactionStatus, TransactionReceipt } from 'web3';
import { strip } from '../utils/ethUtils';
import * as WEB3 from './constants/web3';
import * as PENDING from './constants/pendingTx';
import * as AccountsActions from './AccountsActions';
import * as TokenActions from './TokenActions';
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';
} from 'flowtype';
import type { Account } from '../reducers/AccountsReducer';
import type { PendingTx } from '../reducers/PendingTxReducer';
import type { Web3Instance } from '../reducers/Web3Reducer';
import type { Token } from '../reducers/TokensReducer';
import type { NetworkToken } from '../reducers/LocalStorageReducer';
import type { Account } from 'reducers/AccountsReducer';
import type { PendingTx } from 'reducers/PendingTxReducer';
import type { Web3Instance } from 'reducers/Web3Reducer';
import type { Token } from 'reducers/TokensReducer';
import type { NetworkToken } from 'reducers/LocalStorageReducer';
import * as TokenActions from './TokenActions';
import * as AccountsActions from './AccountsActions';
export type Web3Action = {
type: typeof WEB3.READY,

View File

@ -0,0 +1,56 @@
import styled, { css } from 'styled-components';
import PropTypes from 'prop-types';
import React from 'react';
import colors from 'config/colors';
const Wrapper = styled.button`
padding: 12px 24px;
border-radius: 3px;
font-size: 14px;
font-weight: 300;
cursor: pointer;
background: ${colors.GREEN_PRIMARY};
color: ${colors.WHITE};
border: 0;
&:hover {
background: ${colors.GREEN_SECONDARY};
}
&:active {
background: ${colors.GREEN_TERTIARY};
}
${props => props.disabled && css`
pointer-events: none;
color: ${colors.TEXT_SECONDARY};
background: ${colors.GRAY_LIGHT};
`}
`;
const Button = ({
text, onClick, disabled, blue, white,
}) => (
<Wrapper
onClick={onClick}
disabled={disabled}
blue={blue}
white={white}
>{text}
</Wrapper>
);
Button.propTypes = {
onClick: PropTypes.func,
disabled: PropTypes.bool,
blue: PropTypes.bool,
white: PropTypes.bool,
text: PropTypes.string.isRequired,
};
Button.defaultProps = {
onClick: () => {},
disabled: false,
blue: false,
white: false,
};
export default Button;

View File

@ -0,0 +1,46 @@
import styled from 'styled-components';
import PropTypes from 'prop-types';
import React from 'react';
import { getYear } from 'date-fns';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import colors from 'config/colors';
import * as LogActions from 'actions/LogActions';
const Wrapper = styled.div`
width: 100%;
font-size: 12px;
color: ${colors.TEXT_SECONDARY};
padding: 22px 48px;
border-top: 1px solid ${colors.DIVIDER};
display: flex;
`;
const A = styled.a`
margin: 0 6px;
margin-right: 20px;
`;
const Copy = styled.div`
margin-right: 20px;
`;
const Footer = ({ toggle }) => (
<Wrapper>
<Copy>© {getYear(new Date())}</Copy>
<A href="http://satoshilabs.com" target="_blank" rel="noreferrer noopener" className="satoshi green">SatoshiLabs</A>
<A href="tos.pdf" target="_blank" rel="noreferrer noopener" className="green">Terms</A>
<A onClick={toggle} className="green">Show Log</A>
</Wrapper>
);
Footer.propTypes = {
toggle: PropTypes.func.isRequired,
};
const mapDispatchToProps = dispatch => ({
toggle: bindActionCreators(LogActions.toggle, dispatch),
});
export default connect(null, mapDispatchToProps)(Footer);

View File

@ -1,21 +1,24 @@
/* @flow */
import React from 'react';
import styled from 'styled-components';
import colors from '~/js/config/colors';
import colors from 'config/colors';
const Wrapper = styled.header`
width: 100%;
height: 52px;
background: ${colors.color_header};
background: ${colors.HEADER};
svg {
fill: ${colors.color_white};
height: 28px;
width: 100px;
flex: 1;
}
fill: ${colors.WHITE};
height: 28px;
width: 100px;
flex: 1;
}
`;
const LinkWrapper = styled.div``;
const LayoutWrapper = styled.div`
width: 100%;
height: 100%;
@ -27,11 +30,11 @@ const LayoutWrapper = styled.div`
`;
const A = styled.a`
color: ${colors.color_white};
color: ${colors.WHITE};
margin-left: 24px;
&:visited {
color: ${colors.color_white};
color: ${colors.WHITE};
margin-left: 24px;
}
@ -41,7 +44,7 @@ const A = styled.a`
&:hover,
&:active {
color: ${colors.color_text_secondary};
color: ${colors.TEXT_SECONDARY};
}
`;
@ -57,12 +60,12 @@ const Header = (): React$Element<string> => (
<path d="M79.4,20.3c0-4.5-3.1-7.4-7.7-7.4H61.2v22.3H67v-7.5h2.2l4.1,7.5H80l-4.9-8.3C77.2,26.1,79.4,24,79.4,20.3z M71,22.5h-4V18 h4c1.5,0,2.5,0.9,2.5,2.2C73.5,21.6,72.5,22.5,71,22.5z" />
<polygon points="40.5,12.8 58.6,12.8 58.6,18.1 52.4,18.1 52.4,35.2 46.6,35.2 46.6,18.1 40.5,18.1 " />
</svg>
<div>
<LinkWrapper>
<A href="https://trezor.io/" target="_blank" rel="noreferrer noopener">TREZOR</A>
<A href="https://doc.satoshilabs.com/trezor-user/" target="_blank" rel="noreferrer noopener">Docs</A>
<A href="https://blog.trezor.io/" target="_blank" rel="noreferrer noopener">Blog</A>
<A href="https://trezor.io/support/" target="_blank" rel="noreferrer noopener">Support</A>
</div>
</LinkWrapper>
</LayoutWrapper>
</Wrapper>
);

View File

@ -0,0 +1,41 @@
import styled, { css } from 'styled-components';
import colors from 'config/colors';
const baseStyles = css`
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
color: ${colors.BLACK};
font-weight: bold;
`;
const H1 = styled.h1`
${baseStyles};
font-size: 18px;
`;
const H2 = styled.h2`
${baseStyles};
font-size: 16px;
${props => props.claim && css`
font-size: 36px;
padding-bottom: 24px
`}
`;
const H3 = styled.h3`
${baseStyles};
font-size: 14px;
`;
const H4 = styled.h4`
${baseStyles};
font-size: 12px;
`;
export {
H1,
H2,
H3,
H4,
};

View File

@ -0,0 +1,38 @@
import React from 'react';
import PropTypes from 'prop-types';
const Icon = ({ icon, size = 32, color = 'black' }) => {
const styles = {
svg: {
display: 'inline-block',
verticalAlign: 'middle',
},
path: {
fill: color,
},
};
return (
<svg
style={styles.svg}
width={`${size}`}
height={`${size}`}
viewBox="0 0 1024 1024"
>
<path
style={styles.path}
d={icon}
/>
</svg>
);
};
Icon.propTypes = {
icon: PropTypes.string.isRequired,
size: PropTypes.number,
color: PropTypes.string,
};
export default Icon;

View File

@ -1,6 +1,5 @@
/* @flow */
import React from 'react';
export default (props: { size: string, label?: string, className?: string }): React$Element<string> => {
@ -11,7 +10,7 @@ export default (props: { size: string, label?: string, className?: string }): Re
};
return (
<div className={ className } style={style}>
<div className={className} style={style}>
<p>{ props.label }</p>
<svg className="circular" viewBox="25 25 50 50">
<circle className="route" cx="50" cy="50" r="20" fill="none" stroke="" strokeWidth="1" strokeMiterlimit="10" />

View File

@ -4,28 +4,17 @@
import React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { H2 } from 'components/Heading';
import * as LogActions from '~/js/actions/LogActions';
import type { State, Dispatch } from '~/flowtype';
type Props = {
log: $ElementType<State, 'log'>,
toggle: typeof LogActions.toggle
}
import * as LogActions from 'actions/LogActions';
import type { State, Dispatch } from 'flowtype';
const Log = (props: Props): ?React$Element<string> => {
if (!props.log.opened) return null;
// const entries = props.log.entries.map(entry => {
// return (
// )
// })
return (
<div className="log">
<button className="log-close transparent" onClick={props.toggle} />
<h2>Log</h2>
<H2>Log</H2>
<p>Attention: The log contains your XPUBs. Anyone with your XPUBs can see your account history.</p>
<textarea value={JSON.stringify(props.log.entries)} readOnly />
</div>

View File

@ -2,13 +2,14 @@
import React from 'react';
import { H2 } from 'components/Heading';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as NOTIFICATION from '~/js/actions/constants/notification';
import * as NotificationActions from '~/js/actions/NotificationActions';
import type { Action, State, Dispatch } from '~/flowtype';
import Loader from './LoaderCircle';
import * as NOTIFICATION from 'actions/constants/notification';
import * as NotificationActions from 'actions/NotificationActions';
import type { Action, State, Dispatch } from 'flowtype';
import Loader from 'components/LoaderCircle';
type Props = {
notifications: $ElementType<State, 'notifications'>,
@ -42,7 +43,7 @@ export const Notification = (props: NProps): React$Element<string> => {
/>
) : null }
<div className="notification-body">
<h2>{ props.title }</h2>
<H2>{ props.title }</H2>
{ props.message ? (<p dangerouslySetInnerHTML={{ __html: props.message }} />) : null }
</div>
{ props.actions && props.actions.length > 0 ? (
@ -53,7 +54,8 @@ export const Notification = (props: NProps): React$Element<string> => {
{ props.loading ? (
<Loader
className="info"
size="50" />
size="50"
/>
) : null }
</div>

View File

@ -1,31 +0,0 @@
/* @flow */
import React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as LogActions from '~/js/actions/LogActions';
import type { State, Dispatch } from '~/flowtype';
type Props = {
toggle: typeof LogActions.toggle
}
const Footer = (props: Props): React$Element<string> => (
<footer>
<span>© 2018</span>
<a href="http://satoshilabs.com" target="_blank" rel="noreferrer noopener" className="satoshi green">SatoshiLabs</a>
<a href="tos.pdf" target="_blank" rel="noreferrer noopener" className="green">Terms</a>
<a onClick={props.toggle} className="green">Show Log</a>
</footer>
);
export default connect(
(state: State) => ({
}),
(dispatch: Dispatch) => ({
toggle: bindActionCreators(LogActions.toggle, dispatch),
}),
)(Footer);

View File

@ -1,40 +0,0 @@
// @flow
import styled, { css } from 'styled-components';
import colors from '~/js/config/colors';
const baseStyles = css`
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
color: ${colors.black};
font-weight: bold;
`;
const H1 = styled.h1`
${baseStyles}
font-size: 16px;
`;
const H2 = styled.h2`
${baseStyles};
font-size: 14px;
`;
const H3 = styled.h3`
${baseStyles};
font-size: 12px;
`;
const H4 = styled.h4`
${baseStyles};
font-size: 10px;
`;
const Heading = {
H1,
H2,
H3,
H4,
};
module.exports = Heading;

View File

@ -2,7 +2,7 @@
import React, { Component } from 'react';
import { findAccount } from '~/js/reducers/AccountsReducer';
import { findAccount } from 'reducers/AccountsReducer';
import type { Props } from './index';

View File

@ -2,7 +2,7 @@
import React, { Component } from 'react';
import { getDuplicateInstanceNumber } from '~/js/reducers/utils';
import { getDuplicateInstanceNumber } from 'reducers/utils';
import type { Props } from './index';
type State = {

View File

@ -2,7 +2,7 @@
import React, { Component } from 'react';
import Loader from '../common/LoaderCircle';
import Loader from 'components/LoaderCircle';
import type { Props } from './index';

View File

@ -10,9 +10,14 @@ import { CSSTransition, Transition } from 'react-transition-group';
import { UI } from 'trezor-connect';
import { default as ModalActions } from '~/js/actions/ModalActions';
import { default as ReceiveActions } from '~/js/actions/ReceiveActions';
import { default as ModalActions } from 'actions/ModalActions';
import { default as ReceiveActions } from 'actions/ReceiveActions';
import * as RECEIVE from 'actions/constants/receive';
import * as MODAL from 'actions/constants/modal';
import * as CONNECT from 'actions/constants/TrezorConnect';
import type { MapStateToProps, MapDispatchToProps } from 'react-redux';
import type { State, Dispatch } from 'flowtype';
import Pin from './Pin';
import InvalidPin from './InvalidPin';
import Passphrase from './Passphrase';
@ -22,12 +27,6 @@ import ConfirmAddress, { ConfirmUnverifiedAddress } from './ConfirmAddress';
import RememberDevice, { ForgetDevice } from './RememberDevice';
import DuplicateDevice from './DuplicateDevice';
import * as RECEIVE from '~/js/actions/constants/receive';
import * as MODAL from '~/js/actions/constants/modal';
import * as CONNECT from '~/js/actions/constants/TrezorConnect';
import type { MapStateToProps, MapDispatchToProps } from 'react-redux';
import type { State, Dispatch } from '~/flowtype';
type OwnProps = { }
@ -104,6 +103,8 @@ class Modal extends Component<Props> {
case CONNECT.TRY_TO_DUPLICATE:
component = (<DuplicateDevice {...this.props} />);
break;
default: null;
}
let ch = null;

View File

@ -1,31 +0,0 @@
/* @flow */
import React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
const SignVerify = () => (
<section className="signverify">
<div className="sign">
<h2>Sign message</h2>
<label>Message</label>
<textarea rows="4" maxLength="255" />
<label>Address</label>
<input type="text" />
<label>Signature</label>
<textarea rows="4" maxLength="255" readOnly="readonly" />
</div>
<div className="verify">
<h2>Verify message</h2>
<label>Message</label>
<textarea rows="4" maxLength="255" />
<label>Address</label>
<input type="text" />
<label>Signature</label>
<textarea rows="4" maxLength="255" />
</div>
</section>
);
export default connect(null, null)(SignVerify);

View File

@ -1,141 +0,0 @@
/* @flow */
import React, { PureComponent } from 'react';
import { Link, NavLink } from 'react-router-dom';
import BigNumber from 'bignumber.js';
import { findDeviceAccounts } from '~/js/reducers/AccountsReducer';
import * as stateUtils from '~/js/reducers/utils';
import Loader from '~/js/components/common/LoaderCircle';
import Tooltip from 'rc-tooltip';
import type { Props } from './index';
import type { TrezorDevice, Accounts } from '~/flowtype';
const AccountSelection = (props: Props): ?React$Element<string> => {
const selected = props.wallet.selectedDevice;
if (!selected) return null;
const { location } = props.router;
const urlParams = location.state;
const accounts = props.accounts;
const baseUrl: string = urlParams.deviceInstance ? `/device/${urlParams.device}:${urlParams.deviceInstance}` : `/device/${urlParams.device}`;
const { config } = props.localStorage;
const selectedCoin = config.coins.find(c => c.network === location.state.network);
if (!selectedCoin) return;
const fiatRate = props.fiat.find(f => f.network === selectedCoin.network);
const deviceAccounts: Accounts = findDeviceAccounts(accounts, selected, location.state.network);
let selectedAccounts = deviceAccounts.map((account, i) => {
// const url: string = `${baseUrl}/network/${location.state.network}/account/${i}`;
const url: string = location.pathname.replace(/account+\/([0-9]*)/, `account/${i}`);
let balance: string = 'Loading...';
if (account.balance !== '') {
const pending = stateUtils.getAccountPendingTx(props.pending, account);
const pendingAmount: BigNumber = stateUtils.getPendingAmount(pending, selectedCoin.symbol);
const availableBalance: string = new BigNumber(account.balance).minus(pendingAmount).toString(10);
if (fiatRate) {
const accountBalance = new BigNumber(availableBalance);
const fiat = accountBalance.times(fiatRate.value).toFixed(2);
balance = `${availableBalance} ${selectedCoin.symbol} / $${fiat}`;
} else {
balance = `${availableBalance} ${selectedCoin.symbol}`;
}
}
return (
<NavLink key={i} activeClassName="selected" className="account" to={url}>
{ `Account #${(account.index + 1)}` }
<span>{ account.loaded ? balance : 'Loading...' }</span>
</NavLink>
);
});
if (selectedAccounts.length < 1) {
if (selected.connected) {
const url: string = location.pathname.replace(/account+\/([0-9]*)/, 'account/0');
selectedAccounts = (
<NavLink activeClassName="selected" className="account" to={url}>
Account #1
<span>Loading...</span>
</NavLink>
);
}
}
let discoveryStatus = null;
const discovery = props.discovery.find(d => d.deviceState === selected.state && d.network === location.state.network);
if (discovery) {
if (discovery.completed) {
// TODO: add only if last one is not empty
//if (selectedAccounts.length > 0 && selectedAccounts[selectedAccounts.length - 1])
const lastAccount = deviceAccounts[deviceAccounts.length - 1];
if (lastAccount && (new BigNumber(lastAccount.balance).greaterThan(0) || lastAccount.nonce > 0)) {
discoveryStatus = (
<div className="add-account" onClick={props.addAccount}>
Add account
</div>
);
} else {
const tooltip = (
<div className="aside-tooltip-wrapper">
To add a new account, last account must have some transactions.
</div>
);
discoveryStatus = (
<Tooltip
arrowContent={<div className="rc-tooltip-arrow-inner" />}
overlay={tooltip}
placement="top"
>
<div className="add-account disabled">
Add account
</div>
</Tooltip>
);
}
} else if (!selected.connected || !selected.available) {
discoveryStatus = (
<div className="discovery-status">
Accounts could not be loaded
<span>{ `Connect ${selected.instanceLabel} device` }</span>
</div>
);
} else {
discoveryStatus = (
<div className="discovery-loading">
<Loader size="20" /> Loading accounts...
</div>
);
}
}
let backButton = null;
if (selectedCoin) {
backButton = (
<NavLink to={baseUrl} className={`back ${selectedCoin.network}`}>
<span className={selectedCoin.network}>{ selectedCoin.name }</span>
</NavLink>
);
}
return (
<section>
{ backButton }
<div>
{ selectedAccounts }
</div>
{ discoveryStatus }
</section>
);
};
export default AccountSelection;

View File

@ -1,77 +0,0 @@
/* @flow */
//import React, { Node } from 'react';
import * as React from 'react';
import { Link, NavLink } from 'react-router-dom';
import { TransitionGroup, CSSTransition } from 'react-transition-group';
import { DeviceSelect, DeviceDropdown } from './DeviceSelection';
import AccountSelection from './AccountSelection';
import CoinSelection from './CoinSelection';
import StickyContainer from './StickyContainer';
import type { Props } from './index';
import type { TrezorDevice } from '~/flowtype';
type TransitionMenuProps = {
animationType: string;
children?: React.Node;
}
const TransitionMenu = (props: TransitionMenuProps): React$Element<TransitionGroup> => (
<TransitionGroup component="div" className="transition-container">
<CSSTransition
key={props.animationType}
onExit={() => { window.dispatchEvent(new Event('resize')); }}
onExited={() => window.dispatchEvent(new Event('resize'))}
in
out
classNames={props.animationType}
appear={false}
timeout={300}
>
{ props.children }
</CSSTransition>
</TransitionGroup>
);
const Aside = (props: Props): React$Element<typeof StickyContainer | string> => {
const selected: ?TrezorDevice = props.wallet.selectedDevice;
const { location } = props.router;
if (location.pathname === '/' || !selected) return (<aside />);
let menu = <section />;
if (props.deviceDropdownOpened) {
menu = <DeviceDropdown {...props} />;
} else if (location.state.network) {
menu = (
<TransitionMenu animationType="slide-left">
<AccountSelection {...props} />
</TransitionMenu>
);
} else if (selected.features && !selected.features.bootloader_mode && selected.features.initialized) {
menu = (
<TransitionMenu animationType="slide-right">
<CoinSelection {...props} />
</TransitionMenu>
);
}
return (
<StickyContainer location={location.pathname} deviceSelection={props.deviceDropdownOpened}>
<DeviceSelect {...props} />
{ menu }
<div className="sticky-bottom">
<div className="help">
<a href="https://trezor.io/support/" target="_blank" rel="noreferrer noopener">Need help?</a>
</div>
</div>
</StickyContainer>
);
};
export default Aside;

View File

@ -1,61 +0,0 @@
/* @flow */
import React from 'react';
import { Link, NavLink } from 'react-router-dom';
import type { Props } from './index';
import type { TrezorDevice } from '~/flowtype';
const CoinSelection = (props: Props): React$Element<string> => {
const { location } = props.router;
const { config } = props.localStorage;
const { selectedDevice } = props.wallet;
let baseUrl: string = '';
if (selectedDevice && selectedDevice.features) {
baseUrl = `/device/${selectedDevice.features.device_id}`;
if (selectedDevice.instance) {
baseUrl += `:${selectedDevice.instance}`;
}
}
const walletCoins = config.coins.map((item) => {
const url = `${baseUrl}/network/${item.network}/account/0`;
const className = `coin ${item.network}`;
return (
<NavLink key={item.network} to={url} className={className}>
{ item.name }
</NavLink>
);
});
return (
<section>
{ walletCoins }
<div className="coin-divider">
Other coins <span>(You will be redirected)</span>
</div>
<a href="https://wallet.trezor.io/#/coin/btc" className="coin btc external">
Bitcoin
</a>
<a href="https://wallet.trezor.io/#/coin/ltc" className="coin ltc external">
Litecoin
</a>
<a href="https://wallet.trezor.io/#/coin/bch" className="coin bch external">
Bitcoin Cash
</a>
<a href="https://wallet.trezor.io/#/coin/btg" className="coin btg external">
Bitcoin Gold
</a>
<a href="https://wallet.trezor.io/#/coin/dash" className="coin dash external">
Dash
</a>
<a href="https://wallet.trezor.io/#/coin/zec" className="coin zec external">
Zcash
</a>
</section>
);
};
export default CoinSelection;

View File

@ -1,64 +0,0 @@
/* @flow */
import * as React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { Route, withRouter } from 'react-router-dom';
import Header from '../common/Header';
import Footer from '../common/Footer';
import AccountTabs from './account/AccountTabs';
import DeviceSettingsTabs from './pages/DeviceSettingsTabs';
import AsideContainer from './aside';
import ModalContainer from '../modal';
import Notifications from '../common/Notification';
import Log from '../common/Log';
import type { MapStateToProps, MapDispatchToProps } from 'react-redux';
import type { State, Dispatch } from '~/flowtype';
type WalletContainerProps = {
wallet: $ElementType<State, 'wallet'>,
children?: React.Node
}
type ContentProps = {
children?: React.Node
}
const Content = (props: ContentProps) => (
<article>
<nav>
<Route path="/device/:device/network/:network/account/:account" component={AccountTabs} />
<Route path="/device/:device/device-settings" component={DeviceSettingsTabs} />
</nav>
<Notifications />
<Log />
{ props.children }
<Footer />
</article>
);
const Wallet = (props: WalletContainerProps) => (
<div className="app">
<Header />
{/* <div>{ props.wallet.online ? "ONLINE" : "OFFLINE" }</div> */}
<main>
<AsideContainer />
<Content>
{ props.children }
</Content>
</main>
<ModalContainer />
</div>
);
const mapStateToProps: MapStateToProps<State, {}, WalletContainerProps> = (state: State, own: {}): WalletContainerProps => ({
wallet: state.wallet,
});
export default withRouter(
connect(mapStateToProps, null)(Wallet),
);

View File

@ -1,20 +0,0 @@
/* @flow */
import React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import DashboardImg from '~/images/dashboard.png';
const Dashboard = () => (
<section className="dashboard">
<h2>Dashboard</h2>
<div className="row">
<h2>Please select your coin</h2>
<p>You will gain access to recieving &amp; sending selected coin</p>
<img src={DashboardImg} height="34" width="auto" alt="Dashboard" />
</div>
</section>
);
export default connect(null, null)(Dashboard);

View File

@ -1,18 +0,0 @@
/* @flow */
import React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
export const DeviceSettings = () => (
<section className="device-settings">
<div className="row">
<h2>Device settings is under construction</h2>
<p>Please use Bitcoin wallet interface to change your device settings</p>
<a className="button" href="https://wallet.trezor.io/">Take me to the Bitcoin wallet</a>
</div>
</section>
);
export default connect(null, null)(DeviceSettings);

View File

@ -1,37 +0,0 @@
/* @flow */
import React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { Notification } from '~/js/components/common/Notification';
import * as TrezorConnectActions from '~/js/actions/TrezorConnectActions';
import type { State, Dispatch } from '~/flowtype';
type Props = {
acquiring: boolean;
acquireDevice: typeof TrezorConnectActions.acquire
}
const UnreadableDevice = (props: Props) => {
return (
<section className="acquire">
<Notification
title="Unreadable device"
message="Please install bridge"
className="error"
cancelable={false}
/>
</section>
);
};
export default connect(
(state: State) => ({
acquiring: state.connect.acquiring,
}),
(dispatch: Dispatch) => ({
acquireDevice: bindActionCreators(TrezorConnectActions.acquire, dispatch),
}),
)(UnreadableDevice);

View File

@ -1,30 +1,32 @@
export default {
color_white: '#ffffff',
WHITE: '#FFFFFF',
color_header: '#212121',
color_body: '#E3E3E3',
color_main: '#FBFBFB',
color_landing: '#F9F9F9',
HEADER: '#212121',
BODY: '#E3E3E3',
MAIN: '#FBFBFB',
LANDING: '#F9F9F9',
color_text_primary: '#494949',
color_text_secondary: '#757575',
TEXT_PRIMARY: '#494949',
TEXT_SECONDARY: '#757575',
color_gray_light: '#F2F2F2', // hover menu
color_divider: '#E3E3E3', //#EBEBEB,
GRAY_LIGHT: '#F2F2F2',
DIVIDER: '#E3E3E3',
color_green_primary: '#01B757',
color_green_secondary: '#00AB51',
color_green_tertiary: '#009546',
GREEN_PRIMARY: '#01B757',
GREEN_SECONDARY: '#00AB51',
GREEN_TERTIARY: '#009546',
color_info_primary: '#1E7FF0',
color_info_secondary: '#E1EFFF',
INFO_PRIMARY: '#1E7FF0',
INFO_SECONDARY: '#E1EFFF',
color_warning_primary: '#EB8A00',
color_warning_secondary: '#FFEFD9',
WARNING_PRIMARY: '#EB8A00',
WARNING_SECONDARY: '#FFEFD9',
color_success_primary: '#01B757',
color_success_secondary: '#DFFFEE',
SUCCESS_PRIMARY: '#01B757',
SUCCESS_SECONDARY: '#DFFFEE',
color_error_primary: '#ED1212',
color_error_secondary: '#FFE9E9',
ERROR_PRIMARY: '#ED1212',
ERROR_SECONDARY: '#FFE9E9',
LABEL_COLOR: '#A9A9A9',
};

321
src/js/config/icons.js Normal file
View File

@ -0,0 +1,321 @@
export default {
PLUS: 'M768 512c0 22.080-17.92 40-40 40h-176v176c0 22.080-17.92 40-40 40s-40-17.92-40-40v-176h-176c-22.080 0-40-17.92-40-40s17.92-40 40-40h176v-176c0-22.080 17.92-40 40-40s40 17.92 40 40v176h176c22.080 0 40 17.92 40 40z',
ARROW_LEFT: 'M603.072 757.216l-237.44-219.616c-8.576-8.128-13.632-19.296-13.632-31.040 0.288-11.744 5.056-23.2 13.664-31.040l227.040-208.768c16.928-15.36 43.040-14.176 58.176 3.008 15.424 16.864 13.952 43.392-2.656 59.040l-193.504 177.76 203.904 188.608c8 7.52 12.768 18.080 13.344 29.216 0.608 11.456-3.264 21.696-10.688 30.112-15.456 16.896-41.568 18.080-58.208 2.72z',
CHAT: 'M580.992 256h-137.984c-103.296 0-187.008 85.952-187.008 192 0 96.608 69.536 176.32 160 189.792v130.208l128-128h36.992c103.296 0 187.008-85.952 187.008-192s-83.712-192-187.008-192z',
SKIP: 'M512 256c-141.376 0-256 114.656-256 256 0 141.408 114.624 256 256 256s256-114.592 256-256c0-141.344-114.624-256-256-256zM529.056 631.456v-68.256c-102.4-34.144-136.544 0-170.656 68.256 0-170.656 102.4-204.8 170.656-204.8v-68.256l136.544 136.544-136.544 136.512z',
WARNING: 'M795.616 735.008l-264.896-465.44c-10.272-18.080-27.168-18.080-37.504 0l-264.864 465.44c-10.272 18.176-1.696 32.992 19.040 32.992h529.184c20.8 0 29.376-14.816 19.040-32.992zM549.76 673.12c0 10.464-8.48 18.976-18.912 18.976h-37.792c-10.336 0-18.912-8.512-18.912-18.976v-37.952c0-10.464 8.576-18.976 18.912-18.976h37.792c10.4 0 18.912 8.544 18.912 18.976v37.952zM549.76 559.264c0 10.464-8.48 18.976-18.912 18.976h-37.792c-10.336 0-18.912-8.512-18.912-18.976v-113.856c0-10.464 8.576-18.976 18.912-18.976h37.792c10.4 0 18.912 8.544 18.912 18.976v113.856z',
};
/*
trezor icoomon font pack
{
"icons": [
{
"paths": [
"M381.088 476.352v-89.696c0-72.16 53.696-130.656 119.904-130.656h35.104c66.208 0 119.904 58.496 119.904 130.656v7.616h-69.312c-4.416-36.704-33.248-65.056-68.128-65.056-37.952 0-68.736 33.536-68.736 74.88v72.288h221.184c18.208 0 32.992 15.552 32.992 34.72v222.24c0 19.104-14.784 34.656-32.992 34.656h-318.016c-18.208 0-32.992-15.552-32.992-34.72v-222.24c0-19.168 14.784-34.72 32.992-34.72h28.096z"
],
"tags": [
"icon-unlocked"
],
"defaultCode": 59648,
"grid": 0
},
{
"paths": [
"M671.008 476.352h-14.976v-89.632c0-72.256-53.76-130.72-120.064-130.72h-35.136c-66.304 0-119.744 58.464-119.744 130.72v89.632h-28.096c-18.336 0-32.992 15.424-32.992 34.688v222.272c0 18.944 14.656 34.688 32.992 34.688h318.016c18.336 0 32.992-15.744 32.992-34.688v-222.272c0-19.264-14.656-34.688-32.992-34.688zM449.824 404.064c0-41.44 30.56-74.848 68.736-74.848 34.816 0 63.552 33.728 68.128 70.336v76.768h-136.864v-72.256z"
],
"tags": [
"icon-locked"
],
"defaultCode": 59649,
"grid": 0
},
{
"paths": [
"M276 768h471.968c11.072 0 20.032-9.76 20.032-21.824v-75.968c0-12.064-8.96-21.824-20-21.824h-472c-11.040 0-20 9.76-20 21.824v75.968c0 12.064 8.96 21.824 20 21.824zM503.552 260.192l-231.232 288.128c-6.368 7.904-1.184 20.32 8.448 20.32h462.496c9.664 0 14.816-12.384 8.448-20.32l-231.232-288.128c-4.512-5.6-12.448-5.6-16.928 0z"
],
"tags": [
"icon-eject"
],
"defaultCode": 59650,
"grid": 0
},
{
"paths": [
"M347.392 473.312c17.28-82.24 90.4-142.336 173.92-142.336 31.648 0 61.92 8.704 88.576 24.416 6.656 3.936 12.8 8.672 18.944 13.504l-68.832 68.736 192 33.056-32-198.272-38.4 42.016c-5.92-5.024-12.064-9.728-18.336-14.144-40.928-28.672-89.92-44.288-141.92-44.288-121.664 0-225.12 89.312-245.984 210.368l-3.36 20.896h72.672l2.72-13.952zM676.608 550.688c-17.28 82.24-90.4 142.336-173.92 142.336-31.648 0-61.92-8.704-88.576-24.416-6.624-3.936-12.8-8.672-18.944-13.504l68.832-68.736-192-33.056 32 198.272 38.4-42.016c5.92 5.024 12.032 9.696 18.336 14.144 40.928 28.672 89.92 44.288 141.952 44.288 121.664 0 225.12-89.312 245.984-210.368l3.328-20.864h-72.672l-2.72 13.92z"
],
"tags": [
"icon-refresh"
],
"defaultCode": 59651,
"grid": 0
},
{
"paths": [
"M693.024 330.944c-99.968-99.936-262.080-99.936-362.048 0s-99.968 262.112 0 362.080c99.968 100 262.144 99.936 362.048 0 99.968-99.904 99.968-262.176 0-362.080zM507.904 300.192c27.008 0 48.992 21.984 48.992 49.088 0 27.296-21.984 49.472-48.992 49.472-27.264 0-49.536-22.176-49.536-49.472 0-27.552 21.728-49.088 49.536-49.088zM586.656 660.8c0 10.304-4.96 15.328-15.264 15.328h-126.464c-10.304 0-15.328-5.024-15.328-15.328v-32.256c0-10.304 5.024-15.264 15.328-15.264h23.36v-136.064h-23.872c-10.304 0-15.264-5.024-15.264-15.328v-32.224c0-10.304 4.96-15.264 15.264-15.264h88.288c10.304 0 15.264 4.96 15.264 15.264v183.648h23.424c10.304 0 15.264 4.96 15.264 15.264v32.224z"
],
"tags": [
"icon-info"
],
"defaultCode": 59652,
"grid": 0
},
{
"paths": [
"M580.992 256h-137.984c-103.296 0-187.008 85.952-187.008 192 0 96.608 69.536 176.32 160 189.792v130.208l128-128h36.992c103.296 0 187.008-85.952 187.008-192s-83.712-192-187.008-192z"
],
"tags": [
"icon-chat"
],
"defaultCode": 59653,
"grid": 0
},
{
"paths": [
"M512 256c-141.376 0-256 114.656-256 256 0 141.408 114.624 256 256 256s256-114.592 256-256c0-141.344-114.624-256-256-256zM529.056 631.456v-68.256c-102.4-34.144-136.544 0-170.656 68.256 0-170.656 102.4-204.8 170.656-204.8v-68.256l136.544 136.544-136.544 136.512z"
],
"tags": [
"icon-skip"
],
"defaultCode": 59654,
"grid": 0
},
{
"paths": [
"M739.552 462.144h-71.328c-4.256-13.664-10.208-26.56-17.472-38.56l47.264-47.424c11.2-11.008 11.2-29.056 0-40.192l-20.064-20.032c-11.136-11.104-29.152-11.040-40.192 0l-48.128 48.032c-12.992-7.392-27.072-13.152-42.080-16.992v-62.496c0-15.68-12.672-28.48-28.448-28.48h-28.448c-15.68 0-28.416 12.8-28.416 28.48v62.464c-16.352 4.128-31.68 10.656-45.728 19.2l-40.288-40.224c-11.072-11.040-29.184-11.104-40.288 0l-20.096 20.096c-11.104 11.072-10.976 29.152 0.064 40.288l40.992 40.992c-8.672 15.136-15.168 31.648-18.88 49.152h-53.504c-15.776 0-28.544 12.736-28.544 28.48v28.416c0 15.68 12.768 28.416 28.544 28.416h57.152c5.184 17.152 12.992 32.928 23.008 47.328l-38.656 38.656c-11.136 11.136-11.136 29.216-0.064 40.288l20.064 20.096c11.2 11.040 29.248 11.040 40.32-0.032l43.232-43.2c14.528 7.232 30.336 12.48 46.944 15.2v59.488c0 15.68 12.736 28.448 28.448 28.48h28.448c15.68-0.032 28.448-12.8 28.448-28.48v-66.816c14.336-5.088 27.904-11.872 40.224-20.544l45.76 45.888c11.104 11.072 29.12 11.072 40.224 0l20.096-20.128c11.168-11.072 11.168-29.056-0.096-40.288l-50.144-50.24c6.144-12.512 10.944-25.792 13.92-39.904h67.776c15.744 0 28.448-12.672 28.48-28.448v-28.448c-0.096-15.68-12.8-28.512-28.544-28.512zM504.928 583.072c-39.264 0-71.072-31.776-71.072-71.104 0-39.264 31.808-71.040 71.072-71.040 39.296 0 71.136 31.776 71.136 71.040 0 39.328-31.84 71.104-71.136 71.104z"
],
"tags": [
"icon-cog"
],
"defaultCode": 59655,
"grid": 0
},
{
"paths": [
"M795.616 735.008l-264.896-465.44c-10.272-18.080-27.168-18.080-37.504 0l-264.864 465.44c-10.272 18.176-1.696 32.992 19.040 32.992h529.184c20.8 0 29.376-14.816 19.040-32.992zM549.76 673.12c0 10.464-8.48 18.976-18.912 18.976h-37.792c-10.336 0-18.912-8.512-18.912-18.976v-37.952c0-10.464 8.576-18.976 18.912-18.976h37.792c10.4 0 18.912 8.544 18.912 18.976v37.952zM549.76 559.264c0 10.464-8.48 18.976-18.912 18.976h-37.792c-10.336 0-18.912-8.512-18.912-18.976v-113.856c0-10.464 8.576-18.976 18.912-18.976h37.792c10.4 0 18.912 8.544 18.912 18.976v113.856z"
],
"tags": [
"icon-warning"
],
"defaultCode": 59656,
"grid": 0
},
{
"paths": [
"M757.216 420.928l-219.616 237.44c-8.128 8.576-19.296 13.632-31.040 13.632-11.744-0.288-23.2-5.056-31.040-13.664l-208.768-227.040c-15.36-16.928-14.176-43.040 3.008-58.176 16.864-15.424 43.392-13.952 59.040 2.656l177.76 193.504 188.608-203.904c7.52-8 18.080-12.768 29.216-13.344 11.456-0.608 21.696 3.264 30.112 10.688 16.896 15.456 18.080 41.568 2.72 58.208z"
],
"tags": [
"icon-arrow-down"
],
"defaultCode": 59657,
"grid": 0
},
{
"paths": [
"M754.816 689.92c17.6 17.6 17.6 46.72 0 64.64-8.96 8.64-20.48 13.44-32.64 13.44s-23.68-4.8-32.32-13.44l-177.888-177.92-177.888 177.92c-16.32 16.96-47.040 17.6-64.64 0-17.92-17.92-17.92-47.040 0-64.64l178.208-177.92-178.208-177.92c-17.92-17.92-17.92-46.72 0-64.64 17.28-17.28 47.36-17.28 64.64 0l177.888 177.92 177.888-177.92c17.92-17.92 47.040-17.92 64.96 0 17.6 17.92 17.6 46.72 0 64.64l-178.24 177.92 178.24 177.92z"
],
"tags": [
"icon-close"
],
"defaultCode": 59658,
"grid": 0
},
{
"paths": [
"M757.216 603.072l-219.616-237.44c-8.128-8.576-19.296-13.632-31.040-13.632-11.744 0.288-23.2 5.056-31.040 13.664l-208.768 227.040c-15.36 16.928-14.176 43.040 3.008 58.176 16.864 15.424 43.392 13.952 59.040-2.656l177.76-193.504 188.608 203.904c7.52 8 18.080 12.768 29.216 13.344 11.456 0.608 21.696-3.264 30.112-10.688 16.896-15.456 18.080-41.568 2.72-58.208z"
],
"tags": [
"icon-arrow-up"
],
"defaultCode": 59659,
"grid": 0
},
{
"paths": [
"M420.928 757.216l237.44-219.616c8.576-8.128 13.632-19.296 13.632-31.040-0.288-11.744-5.056-23.2-13.664-31.040l-227.040-208.768c-16.928-15.36-43.040-14.176-58.176 3.008-15.424 16.864-13.952 43.392 2.656 59.040l193.504 177.76-203.904 188.608c-8 7.52-12.768 18.080-13.344 29.216-0.608 11.456 3.264 21.696 10.688 30.112 15.456 16.896 41.568 18.080 58.208 2.72z"
],
"tags": [
"icon-arrow-right2"
],
"defaultCode": 59660,
"grid": 0
},
{
"paths": [
"M768 512c0 22.080-17.92 40-40 40h-176v176c0 22.080-17.92 40-40 40s-40-17.92-40-40v-176h-176c-22.080 0-40-17.92-40-40s17.92-40 40-40h176v-176c0-22.080 17.92-40 40-40s40 17.92 40 40v176h176c22.080 0 40 17.92 40 40z"
],
"tags": [
"icon-plus"
],
"defaultCode": 59661,
"grid": 0
},
{
"paths": [
"M420.928 757.216l237.44-219.616c8.576-8.128 13.632-19.296 13.632-31.040-0.288-11.744-5.056-23.2-13.664-31.040l-227.040-208.768c-16.928-15.36-43.040-14.176-58.176 3.008-15.424 16.864-13.952 43.392 2.656 59.040l193.504 177.76-203.904 188.608c-8 7.52-12.768 18.080-13.344 29.216-0.608 11.456 3.264 21.696 10.688 30.112 15.456 16.896 41.568 18.080 58.208 2.72z"
],
"tags": [
"icon-arrow-right"
],
"defaultCode": 59662,
"grid": 0
},
{
"paths": [
"M693.024 330.944c-99.968-99.936-262.080-99.936-362.048 0s-99.968 262.112 0 362.080c99.968 100 262.144 99.936 362.048 0 99.968-99.904 99.968-262.176 0-362.080zM501.216 717.952c-27.808 0-50.496-22.464-50.496-50.048 0-28.32 22.176-50.528 50.496-50.528 27.616 0 50.048 22.656 50.048 50.528 0.032 27.168-22.88 50.048-50.048 50.048zM536.416 542.464v27.744c0 13.504-5.28 18.784-18.784 18.784h-36.224c-13.504 0-18.72-5.28-18.72-18.784v-61.984c0-15.68 16.064-20.352 30.208-24.48 3.456-1.056 7.040-2.080 10.496-3.264 18.336-6.592 29.696-14.816 29.696-35.296 0-6.656 0-26.816-32.832-26.816-20.224 0-38.624 7.776-49.6 12.416-6.208 2.624-9.28 3.904-12.384 3.904-6.336 0-12.32-5.088-13.248-10.304l-12.608-32.96c-1.824-3.776-1.824-6.784-1.824-9.216 0-24.288 75.552-37.664 100.608-37.664 63.104 0 105.504 40.672 105.504 101.152 0.032 65.44-49.12 85.952-80.288 96.768z"
],
"tags": [
"icon-help"
],
"defaultCode": 59663,
"grid": 0
},
{
"paths": [
"M768 288v160c0 17.6-14.4 32-32 32h-160c-17.6 0-32-14.4-32-32v-160c0-17.6 14.4-32 32-32h160c17.6 0 32 14.4 32 32zM480 576v160c0 17.6-14.4 32-32 32h-160c-17.6 0-32-14.4-32-32v-160c0-17.6 14.4-32 32-32h160c17.6 0 32 14.4 32 32zM480 288v160c0 17.6-14.4 32-32 32h-160c-17.6 0-32-14.4-32-32v-160c0-17.6 14.4-32 32-32h160c17.6 0 32 14.4 32 32zM768 576v160c0 17.6-14.4 32-32 32h-160c-17.6 0-32-14.4-32-32v-160c0-17.6 14.4-32 32-32h160c17.6 0 32 14.4 32 32z"
],
"tags": [
"icon-dashboard"
],
"defaultCode": 59664,
"grid": 0
},
{
"paths": [
"M768 503.36c-20.16 34.88-44.48 63.68-71.68 86.72l-64.64-64.64c0.64-4.16 0.96-8.64 0.96-12.8 0-60.16-51.84-108.8-115.84-108.8-2.24 0-4.16 0-6.4 0.32l-33.92-33.92c12.16-1.6 24-2.24 36.16-2.24 98.88 0 197.44 45.12 255.36 135.36zM348.8 313.92c-8.96-8.96-23.68-8.96-32.64 0l-3.52 3.52c-8.96 8.96-8.96 23.68 0 32.64l53.76 53.76c-43.52 22.4-81.6 56.32-110.4 100.8 83.84 130.56 226.88 177.6 348.48 137.28l57.6 57.6c9.28 9.28 23.68 9.28 32.96 0l3.2-3.2c8.96-8.96 8.96-23.68 0-32.64l-349.44-349.76zM516.8 621.44c-64 0.32-115.84-48.64-115.84-108.48-0.32-21.12 6.080-40.64 17.28-57.28l42.56 42.56c-1.92 5.76-2.56 12.16-1.92 18.88 2.88 30.080 30.72 52.16 62.72 49.92 2.24-0.32 4.8-0.64 7.040-0.96l42.56 42.56c-16.32 8.32-34.56 12.8-54.4 12.8z"
],
"tags": [
"icon-eye-crossed"
],
"defaultCode": 59665,
"grid": 0
},
{
"paths": [
"M603.2 265.6h-6.4c-25.494-5.341-54.79-8.398-84.8-8.398s-59.305 3.058-87.592 8.879l2.792-0.48h-6.72c-30.053 5.643-52.489 31.68-52.489 62.956 0 0.367 0.003 0.733 0.009 1.099l-0.001-0.055v234.88c0.075 40.921 11.238 79.22 30.643 112.071l-0.563-1.031 35.2 60.48c11.655 19.297 32.515 32.001 56.342 32.001 0.105 0 0.209 0 0.314-0.001h44.144c0.359 0.007 0.783 0.011 1.208 0.011 23.569 0 44.162-12.74 55.269-31.709l0.164-0.302 36.16-64c18.232-31.447 29.027-69.173 29.12-109.413v-232.987c0.005-0.293 0.008-0.639 0.008-0.986 0-31.391-22.599-57.503-52.416-62.954l-0.392-0.059zM629.76 563.2c-0.193 35.364-9.792 68.446-26.418 96.923l0.498-0.923-35.84 64c-6.868 11.865-19.463 19.742-33.906 19.84h-44.174c-0.073 0-0.159 0.001-0.246 0.001-14.427 0-27.041-7.762-33.894-19.338l-0.1-0.183-34.88-59.84c-16.656-28.155-26.515-62.042-26.56-98.227v-235.853c0.133-19.025 13.742-34.833 31.751-38.359l0.249-0.041h6.72c24.050-5.126 51.682-8.062 80-8.062s55.949 2.936 82.608 8.519l-2.608-0.457h6.72c18.258 3.568 31.867 19.375 32 38.386v0.014zM422.4 353.92h179.2c3.535 0 6.4 2.865 6.4 6.4v99.2c0 3.535-2.865 6.4-6.4 6.4h-179.2c-3.535 0-6.4-2.865-6.4-6.4v-99.2c0-3.535 2.865-6.4 6.4-6.4z"
],
"tags": [
"icon-T1"
],
"defaultCode": 59666,
"grid": 0
},
{
"paths": [
"M603.2 265.6h-6.4c-25.494-5.341-54.79-8.398-84.8-8.398s-59.305 3.058-87.592 8.879l2.792-0.48h-6.72c-30.053 5.643-52.489 31.68-52.489 62.956 0 0.367 0.003 0.733 0.009 1.099l-0.001-0.055v234.88c0.075 40.921 11.238 79.22 30.643 112.071l-0.563-1.031 35.2 60.48c11.655 19.297 32.515 32.001 56.342 32.001 0.105 0 0.209 0 0.314-0.001h44.144c0.359 0.007 0.783 0.011 1.208 0.011 23.569 0 44.162-12.74 55.269-31.709l0.164-0.302 36.16-64c18.152-31.468 28.933-69.175 29.12-109.385v-233.015c0.005-0.293 0.008-0.639 0.008-0.986 0-31.391-22.599-57.503-52.416-62.954l-0.392-0.059zM629.76 563.2c-0.193 35.364-9.792 68.446-26.418 96.923l0.498-0.923-35.84 64c-6.868 11.865-19.463 19.742-33.906 19.84h-44.174c-14.469-0.112-27.111-7.827-34.139-19.343l-34.981-61.297c-16.687-28.041-26.553-61.827-26.56-97.918v-234.882c0-19.072 13.676-34.95 31.757-38.362l0.243-0.038h6.72c24.050-5.126 51.682-8.062 80-8.062s55.949 2.936 82.608 8.519l-2.608-0.457h6.72c18.324 3.45 32 19.328 32 38.4v0zM422.4 353.92h179.2c3.535 0 6.4 2.865 6.4 6.4v99.2c0 3.535-2.865 6.4-6.4 6.4h-179.2c-3.535 0-6.4-2.865-6.4-6.4v-99.2c0-3.535 2.865-6.4 6.4-6.4zM531.2 490.24h70.4c3.535 0 6.4 2.865 6.4 6.4v28.8c0 3.535-2.865 6.4-6.4 6.4h-70.4c-3.535 0-6.4-2.865-6.4-6.4v-28.8c0-3.535 2.865-6.4 6.4-6.4zM422.4 491.2h70.4c3.535 0 6.4 2.865 6.4 6.4v28.8c0 3.535-2.865 6.4-6.4 6.4h-70.4c-3.535 0-6.4-2.865-6.4-6.4v-28.8c0-3.535 2.865-6.4 6.4-6.4z"
],
"tags": [
"icon-T1-buttons"
],
"defaultCode": 59667,
"grid": 0
},
{
"paths": [
"M526.72 614.080h-29.44c-16.229-0.18-30.307-9.217-37.647-22.496l-0.113-0.224-23.36-41.92c-12.685-22.404-20.16-49.203-20.16-77.748 0-0.004 0-0.008 0-0.012v0.001-164.16c-0.002-0.138-0.002-0.301-0.002-0.463 0-21.403 14.903-39.326 34.898-43.957l0.304-0.059h4.48c16.978-3.729 36.479-5.865 56.48-5.865s39.502 2.136 58.289 6.193l-1.809-0.327h4.48c20.14 4.81 34.883 22.655 34.883 43.943 0 0.189-0.001 0.377-0.003 0.565v-0.029 163.52c0 0.064 0 0.139 0 0.214 0 28.079-7.233 54.468-19.937 77.407l0.417-0.821-24 43.84c-7.529 13.375-21.591 22.288-37.744 22.4h-0.016zM512 274.24c-0.097 0-0.212 0-0.327 0-18.693 0-36.923 1.981-54.492 5.745l1.699-0.305h-4.48c-12.188 2.865-21.122 13.645-21.122 26.512 0 0.129 0.001 0.258 0.003 0.387v-0.020 164.48c0 0.094 0 0.204 0 0.315 0 25.018 6.525 48.512 17.966 68.873l-0.365-0.708 23.36 41.92c4.497 8.071 12.981 13.44 22.718 13.44 0.001 0 0.002 0 0.002 0h29.44c9.799-0.067 18.299-5.56 22.652-13.623l0.068-0.137 24-43.84c10.854-19.495 17.254-42.757 17.28-67.512v-162.248c0.002-0.109 0.002-0.238 0.002-0.368 0-12.867-8.935-23.648-20.938-26.476l-0.184-0.037h-4.48c-15.736-3.739-33.906-6.053-52.557-6.396l-0.243-0.004zM452.48 324.48h119.040c2.474 0 4.48 2.006 4.48 4.48v69.44c0 2.474-2.006 4.48-4.48 4.48h-119.040c-2.474 0-4.48-2.006-4.48-4.48v-69.44c0-2.474 2.006-4.48 4.48-4.48zM540.48 656.32v52.16h-18.24v59.52h-19.84v-59.52h-18.88v-52.16h56.96z"
],
"tags": [
"icon-T1-connect"
],
"defaultCode": 59668,
"grid": 0
},
{
"paths": [
"M551.36 781.76h-78.4c-0.225 0.006-0.489 0.010-0.754 0.010-10.242 0-19.207-5.468-24.135-13.643l-0.071-0.127-64-96c-29.426-43.619-46.99-97.353-47.040-155.187v-233.613c0.36-22.875 18.988-41.281 41.915-41.281 0.114 0 0.228 0 0.342 0.001h263.342c0.097-0.001 0.211-0.001 0.325-0.001 22.927 0 41.555 18.406 41.915 41.248v239.394c-0.289 59.994-19.423 115.463-51.779 160.855l0.579-0.855-60.48 86.080c-4.695 7.399-12.575 12.414-21.664 13.114l-0.096 0.006zM380.48 269.76c-0.1-0.003-0.217-0.004-0.334-0.004-7.552 0-13.716 5.946-14.064 13.413l-0.001 0.031v233.92c0 0.010 0 0.023 0 0.036 0 52.093 15.777 100.502 42.813 140.708l-0.573-0.904 64 96h79.040l60.16-86.080c28.821-40.408 46.080-90.794 46.080-145.211 0-0.024 0-0.049 0-0.073v0.004-238.4c-0.35-7.498-6.513-13.444-14.066-13.444-0.118 0-0.235 0.001-0.352 0.004h0.017z"
],
"defaultCode": 59669,
"grid": 0
},
{
"paths": [
"M407.040 335.68h209.92c4.595 0 8.32 3.725 8.32 8.32v201.92c0 4.595-3.725 8.32-8.32 8.32h-209.92c-4.595 0-8.32-3.725-8.32-8.32v-201.92c0-4.595 3.725-8.32 8.32-8.32z"
],
"defaultCode": 59670,
"grid": 0
},
{
"paths": [
"M539.52 608h-54.72c-6.578-0.052-12.387-3.298-15.96-8.261l-0.040-0.059-45.12-64c-20.029-28.726-32.002-64.366-32.002-102.802 0-0.309 0.001-0.617 0.002-0.925v0.047-157.76c0.349-15.459 12.963-27.856 28.473-27.856 0.34 0 0.679 0.006 1.016 0.018l-0.049-0.001h184.32c0.288-0.010 0.627-0.016 0.967-0.016 15.51 0 28.124 12.398 28.473 27.824l0.001 0.032v160c-0.074 40.641-13.522 78.128-36.176 108.308l0.336-0.468-42.24 57.28c-3.622 5.258-9.609 8.66-16.39 8.66-0.313 0-0.624-0.007-0.934-0.022l0.044 0.002zM419.84 265.6c-0.205-0.016-0.444-0.025-0.686-0.025-4.973 0-9.062 3.781-9.551 8.624l-0.003 0.040v155.84c0.066 34.769 11.081 66.953 29.778 93.302l-0.338-0.502 45.12 64h56l42.24-57.28c19.839-26.468 31.828-59.817 32-95.96v-160.040c-0.492-4.884-4.582-8.665-9.554-8.665-0.241 0-0.481 0.009-0.717 0.026l0.032-0.002z"
],
"defaultCode": 59671,
"grid": 0
},
{
"paths": [
"M438.4 309.12h146.88c3.181 0 5.76 2.579 5.76 5.76v134.4c0 3.181-2.579 5.76-5.76 5.76h-146.88c-3.181 0-5.76-2.579-5.76-5.76v-134.4c0-3.181 2.579-5.76 5.76-5.76z"
],
"defaultCode": 59672,
"grid": 0
},
{
"paths": [
"M541.12 659.52v50.56h-18.56v57.92h-20.48v-57.92h-18.88v-50.56h57.92z"
],
"defaultCode": 59673,
"grid": 0
},
{
"paths": [
"M603.072 757.216l-237.44-219.616c-8.576-8.128-13.632-19.296-13.632-31.040 0.288-11.744 5.056-23.2 13.664-31.040l227.040-208.768c16.928-15.36 43.040-14.176 58.176 3.008 15.424 16.864 13.952 43.392-2.656 59.040l-193.504 177.76 203.904 188.608c8 7.52 12.768 18.080 13.344 29.216 0.608 11.456-3.264 21.696-10.688 30.112-15.456 16.896-41.568 18.080-58.208 2.72z"
],
"tags": [
"icon-arrow-left"
],
"defaultCode": 59674,
"grid": 0
},
{
"paths": [
"M677.44 613.76c-3.255 1.423-7.047 2.252-11.033 2.252-0.284 0-0.566-0.004-0.848-0.013l0.041 0.001c-8.323-0.531-15.657-4.371-20.77-10.206l-0.030-0.034-93.44-109.44c-0.378-0.735-1.131-1.229-1.999-1.229-1.237 0-2.24 1.003-2.24 2.24 0 0.209 0.029 0.412 0.083 0.605l-0.004-0.016v233.28c0.102 0.987 0.16 2.132 0.16 3.291 0 18.733-15.187 33.92-33.92 33.92s-33.92-15.187-33.92-33.92c0-1.159 0.058-2.304 0.172-3.433l-0.012 0.142v-236.16c0.050-0.177 0.079-0.379 0.079-0.589 0-1.237-1.003-2.24-2.24-2.24-0.868 0-1.621 0.494-1.993 1.216l-0.006 0.013-88.32 104.32c-5.204 6.343-13.042 10.358-21.819 10.358-7.711 0-14.699-3.099-19.784-8.121l0.003 0.003c-6.16-5.845-9.993-14.090-9.993-23.231 0-8.17 3.062-15.625 8.101-21.28l-0.028 0.032 146.56-173.44c5.311-6.15 13.061-10.069 21.731-10.24h0.029c8.727 0.036 16.523 3.991 21.724 10.196l0.036 0.044 152 178.56c5.441 6.124 8.764 14.234 8.764 23.121 0 12.698-6.785 23.81-16.927 29.911l-0.157 0.088zM329.28 292.8c-0.024-0.488-0.038-1.060-0.038-1.635 0-18.891 14.881-34.306 33.561-35.163l0.077-0.003h292.48c18.795 1.81 33.372 17.523 33.372 36.64s-14.577 34.83-33.222 36.628l-0.15 0.012h-292.48c-18.751-0.866-33.625-16.278-33.625-35.165 0-0.463 0.009-0.923 0.027-1.381l-0.002 0.066z"
],
"tags": [
"icon-top"
],
"defaultCode": 59675,
"grid": 0
},
{
"paths": [
"M692.8 313.92l-1.92-1.92c-6.246-7.057-15.326-11.484-25.44-11.484s-19.194 4.427-25.409 11.448l-0.031 0.036-196.48 224-3.84 1.6-3.84-1.92-48.64-57.28c-7.010-7.905-17.193-12.862-28.533-12.862-21.031 0-38.080 17.049-38.080 38.080 0 7.495 2.165 14.485 5.905 20.377l-0.092-0.155 100.8 148.16c5.391 8.036 14.386 13.292 24.618 13.44h8.662c17.251-0.146 32.385-9.075 41.163-22.529l0.117-0.191 195.2-296.32c4.473-6.632 7.141-14.803 7.141-23.597 0-11.162-4.297-21.32-11.326-28.911l0.025 0.028z"
],
"tags": [
"icon-check"
],
"defaultCode": 59676,
"grid": 0
},
{
"paths": [
"M693.12 330.88c-46.317-46.267-110.276-74.88-180.919-74.88-141.385 0-256 114.615-256 256s114.615 256 256 256c70.642 0 134.602-28.613 180.921-74.882l-0.002 0.002c46.387-46.337 75.081-110.377 75.081-181.12s-28.694-134.783-75.079-181.118l-0.002-0.002zM494.080 344.32h53.12c16 0 18.24 9.28 18.24 14.72v10.24l-10.88 194.56c0 14.4-8 17.28-18.88 17.28h-28.16c-10.56 0-17.28-2.88-18.88-17.92l-10.88-193.92v-10.56c-1.28-4.8 2.24-14.080 16.32-14.080zM521.28 717.76c-0.095 0.001-0.207 0.001-0.319 0.001-27.747 0-50.24-22.493-50.24-50.24s22.493-50.24 50.24-50.24c27.747 0 50.24 22.493 50.24 50.24 0 0.112 0 0.224-0.001 0.336v-0.017c0 0 0 0.001 0 0.001 0 27.634-22.311 50.057-49.903 50.239h-0.017z"
],
"tags": [
"icon-error"
],
"defaultCode": 59677,
"grid": 0
},
{
"paths": [
"M512.64 368c-99.2 0-198.4 45.76-256.64 136.64 128.64 200 394.56 203.84 512-1.28-57.92-90.24-156.48-135.36-255.36-135.36zM516.8 621.44c-64 0.32-115.84-48.64-115.84-108.48-0.32-60.16 51.52-109.12 115.84-109.12 64 0 115.84 48.64 115.84 108.8 0.32 60.16-51.52 108.8-115.84 108.8zM574.72 508.16c2.56 30.080-21.12 56.32-53.12 58.88-32 2.24-59.84-19.84-62.72-49.92-2.56-30.080 21.44-56.32 53.12-58.56 32-2.56 59.84 19.84 62.72 49.6z"
],
"tags": [
"icon-eye"
],
"defaultCode": 59678,
"grid": 0
},
{
"paths": [
"M656.224 402.304l-66.848 66.176-66.848-66.176-50.144 49.6 66.912 66.176-66.912 66.176 50.176 49.632 66.848-66.176 66.848 66.176 50.112-49.632-66.816-66.176 66.816-66.176-50.144-49.6zM337.824 256h540.928c27.2 0 49.248 21.824 49.248 48.768v414.464c0 26.944-22.048 48.768-49.248 48.768h-540.608c-13.856 0-27.072-5.792-36.416-15.936l-192.896-209.664c-17.248-18.752-17.088-47.488 0.352-66.048l192.576-204.8c9.344-9.92 22.4-15.552 36.064-15.552z"
],
"tags": [
"icon-back"
],
"defaultCode": 59679,
"grid": 0
}
]
}
*/

View File

@ -0,0 +1,17 @@
export const FONT_SIZE = {
SMALLER: '12px',
SMALL: '14px',
BASE: '16px',
};
export const TRANSITION_TIME = {
BASE: '0.3s',
};
export const ICON_SIZE = {
BASE: '20px',
};
export const BORDER_WIDTH = {
SELECTED: '3px',
};

View File

@ -0,0 +1,8 @@
export default [
{ id: 'Windows', value: 'trezor-bridge-2.0.11-win32-install.exe', label: 'Windows' },
{ id: 'macOS', value: 'trezor-bridge-2.0.11.pkg', label: 'Mac OS X' },
{ id: 'Linux', value: 'trezor-bridge_2.0.11_amd64.deb', label: 'Linux 64-bit (deb)' },
{ id: 'Linux-rpm', value: 'trezor-bridge_2.0.11_amd64.rpm', label: 'Linux 64-bit (rpm)' },
{ id: '01', value: 'trezor-bridge_2.0.11_amd32.deb', label: 'Linux 32-bit (deb)' },
{ id: '02', value: 'trezor-bridge_2.0.11_amd32.rpm', label: 'Linux 32-bit (rpm)' },
];

32
src/js/constants/coins.js Normal file
View File

@ -0,0 +1,32 @@
export default [
{
coinName: 'Bitcoin',
url: 'https://wallet.trezor.io/#/coin/btc',
image: '../images/btc-logo.png',
},
{
coinName: 'Litecoin',
url: 'https://wallet.trezor.io/#/coin/ltc',
image: '../images/ltc-logo.png',
},
{
coinName: 'Bitcoin Cash',
url: 'https://wallet.trezor.io/#/coin/bch',
image: '../images/bch-logo.png',
},
{
coinName: 'Bitcoin Gold',
url: 'https://wallet.trezor.io/#/coin/btg',
image: '../images/btg-logo.png',
},
{
coinName: 'Dash',
url: 'https://wallet.trezor.io/#/coin/dash',
image: '../images/dash-logo.png',
},
{
coinName: 'Zcash',
url: 'https://wallet.trezor.io/#/coin/zec',
image: '../images/zec-logo.png',
},
];

View File

@ -1,23 +1,20 @@
/* @flow */
import React from 'react';
import { render } from 'react-dom';
import baseStyles from 'support/BaseStyles';
import { onBeforeUnload } from 'actions/WalletActions';
import 'styles/index.less';
import App from 'views/index';
import store from './store';
import router from './router';
import { onBeforeUnload } from './actions/WalletActions';
import styles from '~/styles/index.less';
const root: ?HTMLElement = document.getElementById('root');
if (root) {
render(router, root);
baseStyles();
render(<App />, root);
}
window.onbeforeunload = () => {
store.dispatch(onBeforeUnload());
};
if (typeof module !== undefined && module.hasOwnProperty('hot')) {
// $FlowIssue
module.hot.accept();
}
// Application life cycle starts in ./services/WalletService.js
// Application life cycle starts in services/WalletService.js

View File

@ -1,16 +1,16 @@
/* @flow */
import * as CONNECT from '../actions/constants/TrezorConnect';
import * as WALLET from '../actions/constants/wallet';
import * as ACCOUNT from '../actions/constants/account';
import * as CONNECT from 'actions/constants/TrezorConnect';
import * as WALLET from 'actions/constants/wallet';
import * as ACCOUNT from 'actions/constants/account';
import type { Action, TrezorDevice } from '~/flowtype';
import type { Action, TrezorDevice } from 'flowtype';
import type {
AccountCreateAction,
AccountSetBalanceAction,
AccountSetNonceAction,
} from '../actions/AccountsActions';
} from 'actions/AccountsActions';
export type Account = {
loaded: boolean;

View File

@ -1,12 +1,13 @@
/* @flow */
import { TRANSPORT, DEVICE } from 'trezor-connect';
import * as CONNECT from '../actions/constants/TrezorConnect';
import * as WALLET from '../actions/constants/wallet';
import { getDuplicateInstanceNumber } from './utils';
import { DEVICE } from 'trezor-connect';
import type { Device } from 'trezor-connect';
import * as CONNECT from 'actions/constants/TrezorConnect';
import * as WALLET from 'actions/constants/wallet';
import { getDuplicateInstanceNumber } from 'reducers/utils';
import type { Action, Device, TrezorDevice } from '~/flowtype';
import type { Action, TrezorDevice } from 'flowtype';
export type State = Array<TrezorDevice>;
@ -38,26 +39,25 @@ const mergeDevices = (current: TrezorDevice, upcoming: Device | TrezorDevice): T
instanceName: typeof upcoming.instanceName === 'string' ? upcoming.instanceName : current.instanceName,
state: current.state,
ts: typeof upcoming.ts === 'number' ? upcoming.ts : current.ts,
}
};
if (upcoming.type === 'acquired') {
return { ...upcoming, ...extended };
} else if (upcoming.type === 'unacquired' && current.features && current.state) {
return { ...upcoming, ...extended };
} if (upcoming.type === 'unacquired' && current.features && current.state) {
// corner-case: trying to merge unacquired device with acquired
// make sure that sensitive fields will not be changed and device will remain acquired
return {
type: 'acquired',
path: upcoming.path,
...current,
...extended
}
} else {
return {
...upcoming,
features: null,
...extended
}
...extended,
};
}
return {
...upcoming,
features: null,
...extended,
};
};
const addDevice = (state: State, device: Device): State => {
@ -72,10 +72,9 @@ const addDevice = (state: State, device: Device): State => {
}
otherDevices = state.filter(d => affectedDevices.indexOf(d) === -1);
} else {
affectedDevices = state.filter(d =>
d.features &&
device.features &&
d.features.device_id === device.features.device_id);
affectedDevices = state.filter(d => d.features
&& device.features
&& d.features.device_id === device.features.device_id);
const unacquiredDevices = state.filter(d => d.path.length > 0 && d.path === device.path);
otherDevices = state.filter(d => affectedDevices.indexOf(d) < 0 && unacquiredDevices.indexOf(d) < 0);
}
@ -90,17 +89,17 @@ const addDevice = (state: State, device: Device): State => {
instanceLabel: device.label,
instanceName: null,
ts: new Date().getTime(),
}
};
const newDevice: TrezorDevice = device.type === 'acquired' ? {
...device,
// acquiring: false,
...extended
...extended,
} : {
...device,
features: null,
...extended
...extended,
};
if (affectedDevices.length > 0) {
@ -131,12 +130,11 @@ const addDevice = (state: State, device: Device): State => {
// changedDevices.push(newDevice);
// }
const changedDevices: Array<TrezorDevice> = affectedDevices.filter(d =>
d.features && device.features &&
d.features.passphrase_protection === device.features.passphrase_protection).map(d => {
const extended: Object = { connected: true, available: true }
return mergeDevices(d, { ...device, ...extended })
});
const changedDevices: Array<TrezorDevice> = affectedDevices.filter(d => d.features && device.features
&& d.features.passphrase_protection === device.features.passphrase_protection).map((d) => {
const extended: Object = { connected: true, available: true };
return mergeDevices(d, { ...device, ...extended });
});
if (changedDevices.length !== affectedDevices.length) {
changedDevices.push(newDevice);
}
@ -174,8 +172,7 @@ const changeDevice = (state: State, device: Device | TrezorDevice, extended: Obj
// find devices with the same device_id and passphrase_protection settings
// or devices with the same path (TODO: should be that way?)
const affectedDevices: Array<TrezorDevice> = state.filter(d =>
(d.features && device.features && d.features.device_id === device.features.device_id && d.features.passphrase_protection === device.features.passphrase_protection)
const affectedDevices: Array<TrezorDevice> = state.filter(d => (d.features && device.features && d.features.device_id === device.features.device_id && d.features.passphrase_protection === device.features.passphrase_protection)
|| (d.features && d.path.length > 0 && d.path === device.path));
const otherDevices: Array<TrezorDevice> = state.filter(d => affectedDevices.indexOf(d) === -1);
@ -207,15 +204,15 @@ const devicesFromStorage = (devices: Array<TrezorDevice>): State => devices.map(
connected: false,
available: false,
path: '',
}
};
return device.type === 'acquired' ? {
...device,
...extended
...extended,
} : {
...device,
features: null,
...extended
...extended,
};
});
@ -236,7 +233,7 @@ const disconnectDevice = (state: State, device: Device): State => {
const otherDevices: State = state.filter(d => affectedDevices.indexOf(d) === -1);
if (affectedDevices.length > 0) {
const acquiredDevices = affectedDevices.filter(d => d.features && d.state).map(d => {
const acquiredDevices = affectedDevices.filter(d => d.features && d.state).map((d) => {
if (d.type === 'acquired') {
d.connected = false;
d.available = false;
@ -255,7 +252,7 @@ const onSelectedDevice = (state: State, device: ?TrezorDevice): State => {
if (device) {
const otherDevices: Array<TrezorDevice> = state.filter(d => d !== device);
device.ts = new Date().getTime();
return otherDevices.concat([ device ]);
return otherDevices.concat([device]);
}
return state;
};

View File

@ -3,22 +3,22 @@
import HDKey from 'hdkey';
import * as DISCOVERY from '../actions/constants/discovery';
import * as ACCOUNT from '../actions/constants/account';
import * as CONNECT from '../actions/constants/TrezorConnect';
import * as WALLET from '../actions/constants/wallet';
import * as DISCOVERY from 'actions/constants/discovery';
import * as ACCOUNT from 'actions/constants/account';
import * as CONNECT from 'actions/constants/TrezorConnect';
import * as WALLET from 'actions/constants/wallet';
import type { Action, TrezorDevice } from '~/flowtype';
import type { Action, TrezorDevice } from 'flowtype';
import type {
DiscoveryStartAction,
DiscoveryWaitingAction,
DiscoveryStopAction,
DiscoveryCompleteAction,
} from '../actions/DiscoveryActions';
} from 'actions/DiscoveryActions';
import type {
AccountCreateAction,
} from '../actions/AccountsActions';
} from 'actions/AccountsActions';
export type Discovery = {
network: string;

View File

@ -1,10 +1,10 @@
/* @flow */
import { RATE_UPDATE } from '../services/CoinmarketcapService';
import { RATE_UPDATE } from 'services/CoinmarketcapService';
import type { Action } from '~/flowtype';
import type { FiatRateAction } from '../services/CoinmarketcapService';
import type { Action } from 'flowtype';
import type { FiatRateAction } from 'services/CoinmarketcapService';
export type Fiat = {
+network: string;

View File

@ -1,9 +1,9 @@
/* @flow */
import * as STORAGE from '../actions/constants/localStorage';
import * as STORAGE from 'actions/constants/localStorage';
import type { Action } from '~/flowtype';
import type { Action } from 'flowtype';
export type Coin = {
name: string;

View File

@ -1,8 +1,8 @@
/* @flow */
import * as LOG from '../actions/constants/log';
import type { Action } from '~/flowtype';
import * as LOG from 'actions/constants/log';
import type { Action } from 'flowtype';
export type LogEntry = {
time: number;

View File

@ -2,11 +2,11 @@
import { UI, DEVICE } from 'trezor-connect';
import * as RECEIVE from '../actions/constants/receive';
import * as MODAL from '../actions/constants/modal';
import * as CONNECT from '../actions/constants/TrezorConnect';
import * as RECEIVE from 'actions/constants/receive';
import * as MODAL from 'actions/constants/modal';
import * as CONNECT from 'actions/constants/TrezorConnect';
import type { Action, TrezorDevice } from '~/flowtype';
import type { Action, TrezorDevice } from 'flowtype';
export type State = {
opened: false;

View File

@ -2,10 +2,10 @@
import { LOCATION_CHANGE } from 'react-router-redux';
import * as NOTIFICATION from '../actions/constants/notification';
import * as NOTIFICATION from 'actions/constants/notification';
import { DEVICE } from 'trezor-connect';
import type { Action } from '~/flowtype';
import type { Action } from 'flowtype';
export type CallbackAction = {
label: string;

View File

@ -1,12 +1,12 @@
/* @flow */
import * as PENDING from '../actions/constants/pendingTx';
import * as SEND from '../actions/constants/send';
import * as WEB3 from '../actions/constants/web3';
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';
import type { Action } from 'flowtype';
import type { SendTxAction } from 'actions/SendFormActions';
export type PendingTx = {
+id: string;

View File

@ -2,9 +2,9 @@
import { UI } from 'trezor-connect';
import * as RECEIVE from '../actions/constants/receive';
import * as ACCOUNT from '../actions/constants/account';
import type { Action } from '~/flowtype';
import * as RECEIVE from 'actions/constants/receive';
import * as ACCOUNT from 'actions/constants/account';
import type { Action } from 'flowtype';
export type State = {

View File

@ -1,7 +1,7 @@
/* @flow */
import * as ACCOUNT from '../actions/constants/account';
import * as ACCOUNT from 'actions/constants/account';
import type {
Action,
@ -11,7 +11,7 @@ import type {
PendingTx,
Discovery,
Web3Instance,
} from '~/flowtype';
} from 'flowtype';
export type State = {
location?: string;
@ -38,7 +38,6 @@ export default (state: State = initialState, action: Action): State => {
switch (action.type) {
case ACCOUNT.UPDATE_SELECTED_ACCOUNT:
return action.payload;
default:
return state;
}

View File

@ -3,17 +3,17 @@
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 * 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';
import { getFeeLevels } from 'actions/SendFormActions';
import type { Action } from '~/flowtype';
import type { Action } from 'flowtype';
import type {
Web3UpdateGasPriceAction,
} from '../actions/Web3Actions';
} from 'actions/Web3Actions';
export type State = {
+networkName: string;

View File

@ -1,9 +1,9 @@
/* @flow */
import * as ACCOUNT from '../actions/constants/account';
import * as SUMMARY from '../actions/constants/summary';
import type { Action } from '~/flowtype';
import * as ACCOUNT from 'actions/constants/account';
import * as SUMMARY from 'actions/constants/summary';
import type { Action } from 'flowtype';
import type { NetworkToken } from './LocalStorageReducer';
export type State = {

View File

@ -1,11 +1,11 @@
/* @flow */
import * as CONNECT from '../actions/constants/TrezorConnect';
import * as WALLET from '../actions/constants/wallet';
import * as TOKEN from '../actions/constants/token';
import * as CONNECT from 'actions/constants/TrezorConnect';
import * as WALLET from 'actions/constants/wallet';
import * as TOKEN from 'actions/constants/token';
import type { Action, TrezorDevice } from '~/flowtype';
import type { Action, TrezorDevice } from 'flowtype';
import type { Account } from './AccountsReducer';
export type Token = {

View File

@ -2,10 +2,10 @@
import { TRANSPORT, DEVICE, UI } from 'trezor-connect';
import * as CONNECT from '../actions/constants/TrezorConnect';
import * as WALLET from '../actions/constants/wallet';
import * as CONNECT from 'actions/constants/TrezorConnect';
import * as WALLET from 'actions/constants/wallet';
import type { Action, Device, TrezorDevice } from '~/flowtype';
import type { Action } from 'flowtype';
export type SelectedDevice = {
id: string; // could be device path if unacquired or features.device_id

View File

@ -3,13 +3,13 @@
import { LOCATION_CHANGE } from 'react-router-redux';
import { DEVICE } from 'trezor-connect';
import * as MODAL from '../actions/constants/modal';
import * as WEB3 from '../actions/constants/web3';
import * as WALLET from '../actions/constants/wallet';
import * as CONNECT from '../actions/constants/TrezorConnect';
import * as MODAL from 'actions/constants/modal';
import * as WEB3 from 'actions/constants/web3';
import * as WALLET from 'actions/constants/wallet';
import * as CONNECT from 'actions/constants/TrezorConnect';
import type { Action, RouterLocationState, TrezorDevice } from '~/flowtype';
import type { Action, RouterLocationState, TrezorDevice } from 'flowtype';
type State = {
ready: boolean;

View File

@ -4,14 +4,14 @@
import Web3 from 'web3';
import type { ContractFactory } from 'web3';
import * as STORAGE from '../actions/constants/localStorage';
import * as WEB3 from '../actions/constants/web3';
import * as STORAGE from 'actions/constants/localStorage';
import * as WEB3 from 'actions/constants/web3';
import type { Action } from '~/flowtype';
import type { Action } from 'flowtype';
import type {
Web3UpdateBlockAction,
Web3UpdateGasPriceAction,
} from '../actions/Web3Actions';
} from 'actions/Web3Actions';
export type Web3Instance = {
network: string;

View File

@ -1,26 +1,24 @@
/* @flow */
import { combineReducers } from 'redux';
import { routerReducer } from 'react-router-redux';
import log from './LogReducer.js';
import localStorage from './LocalStorageReducer.js';
import connect from './TrezorConnectReducer.js';
import notifications from './NotificationReducer.js';
import modal from './ModalReducer.js';
import web3 from './Web3Reducer.js';
import accounts from './AccountsReducer.js';
import selectedAccount from './SelectedAccountReducer.js';
import sendForm from './SendFormReducer.js';
import receive from './ReceiveReducer.js';
import summary from './SummaryReducer.js';
import tokens from './TokensReducer.js';
import discovery from './DiscoveryReducer.js';
import pending from './PendingTxReducer.js';
import fiat from './FiatRateReducer.js';
import wallet from './WalletReducer.js';
import devices from './DevicesReducer.js';
import log from 'reducers/LogReducer';
import localStorage from 'reducers/LocalStorageReducer';
import connect from 'reducers/TrezorConnectReducer';
import notifications from 'reducers/NotificationReducer';
import modal from 'reducers/ModalReducer';
import web3 from 'reducers/Web3Reducer';
import accounts from 'reducers/AccountsReducer';
import selectedAccount from 'reducers/SelectedAccountReducer';
import sendForm from 'reducers/SendFormReducer';
import receive from 'reducers/ReceiveReducer';
import summary from 'reducers/SummaryReducer';
import tokens from 'reducers/TokensReducer';
import discovery from 'reducers/DiscoveryReducer';
import pending from 'reducers/PendingTxReducer';
import fiat from 'reducers/FiatRateReducer';
import wallet from 'reducers/WalletReducer';
import devices from 'reducers/DevicesReducer';
const reducers = {
router: routerReducer,

View File

@ -1,9 +1,9 @@
/* @flow */
import * as LogActions from '~/js/actions/LogActions';
import * as STORAGE from '~/js/actions/constants/localStorage';
import * as WALLET from '~/js/actions/constants/wallet';
import * as LogActions from 'actions/LogActions';
import * as STORAGE from 'actions/constants/localStorage';
import * as WALLET from 'actions/constants/wallet';
import BigNumber from 'bignumber.js';
import type {
@ -23,7 +23,7 @@ import type {
Token,
PendingTx,
Web3Instance,
} from '~/flowtype';
} from 'flowtype';
export const getSelectedDevice = (state: State): ?TrezorDevice => {
const locationState = state.router.location.state;

View File

@ -1,52 +0,0 @@
/* @flow */
import React from 'react';
import { Route, Switch } from 'react-router-dom';
import { Provider } from 'react-redux';
import { ConnectedRouter } from 'react-router-redux';
import store, { history } from '../store';
import LandingPageContainer from '../components/landing';
import WalletContainer from '../components/wallet';
import BootloaderContainer from '../components/wallet/pages/Bootloader';
import InitializeContainer from '../components/wallet/pages/Initialize';
import AcquireContainer from '../components/wallet/pages/Acquire';
import UnreadableDeviceContainer from '../components/wallet/pages/UnreadableDevice';
import DashboardContainer from '../components/wallet/pages/Dashboard';
import SummaryContainer from '../components/wallet/account/summary';
import SendFormContainer from '../components/wallet/account/send';
import ReceiveContainer from '../components/wallet/account/receive';
import SignVerifyContainer from '../components/wallet/account/sign/SignVerify';
import DeviceSettingsContainer from '../components/wallet/pages/DeviceSettings';
import WalletSettingsContainer from '../components/wallet/pages/WalletSettings';
export default (
<Provider store={store}>
<ConnectedRouter history={history}>
<Switch>
<Route exact path="/" component={LandingPageContainer} />
<Route exact path="/bridge" component={LandingPageContainer} />
<Route exact path="/import" component={LandingPageContainer} />
<Route>
<WalletContainer>
<Route exact path="/settings" component={WalletSettingsContainer} />
<Route exact path="/device/:device/" component={DashboardContainer} />
<Route exact path="/device/:device/network/:network" component={DashboardContainer} />
<Route exact path="/device/:device/acquire" component={AcquireContainer} />
<Route exact path="/device/:device/unreadable" component={UnreadableDeviceContainer} />
<Route exact path="/device/:device/bootloader" component={BootloaderContainer} />
<Route exact path="/device/:device/initialize" component={InitializeContainer} />
<Route exact path="/device/:device/settings" component={DeviceSettingsContainer} />
<Route exact path="/device/:device/network/:network/account/:account" component={SummaryContainer} />
<Route path="/device/:device/network/:network/account/:account/send" component={SendFormContainer} />
<Route path="/device/:device/network/:network/account/:account/send/override" component={SendFormContainer} />
<Route path="/device/:device/network/:network/account/:account/receive" component={ReceiveContainer} />
<Route path="/device/:device/network/:network/account/:account/signverify" component={SignVerifyContainer} />
</WalletContainer>
</Route>
</Switch>
</ConnectedRouter>
</Provider>
);

View File

@ -1,9 +1,8 @@
/* @flow */
import { JSONRequest, httpRequest } from '../utils/networkUtils';
import { resolveAfter } from '../utils/promiseUtils';
import { READY } from '../actions/constants/localStorage';
import { JSONRequest, httpRequest } from 'utils/networkUtils';
import { resolveAfter } from 'utils/promiseUtils';
import { READY } from 'actions/constants/localStorage';
import type {
Middleware,
@ -14,8 +13,8 @@ import type {
Action,
AsyncAction,
GetState,
} from '~/flowtype';
import type { Config, FiatValueTicker } from '../reducers/LocalStorageReducer';
} from 'flowtype';
import type { Config, FiatValueTicker } from 'reducers/LocalStorageReducer';
export const RATE_UPDATE: 'rate__update' = 'rate__update';

View File

@ -3,18 +3,18 @@
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 LocalStorageActions from 'actions/LocalStorageActions';
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';
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';
import type {
Middleware,
@ -25,13 +25,13 @@ import type {
Action,
AsyncAction,
GetState,
} from '~/flowtype';
} 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';
import type { Discovery } from '../reducers/DiscoveryReducer';
import type { TrezorDevice } from 'flowtype';
import type { Account } from 'reducers/AccountsReducer';
import type { Token } from 'reducers/TokensReducer';
import type { PendingTx } from 'reducers/PendingTxReducer';
import type { Discovery } from 'reducers/DiscoveryReducer';
// https://github.com/STRML/react-localstorage/blob/master/react-localstorage.js

View File

@ -1,10 +1,10 @@
/* @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 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 { TRANSPORT, DEVICE } from 'trezor-connect';
import type {
@ -16,7 +16,7 @@ import type {
Action,
AsyncAction,
GetState,
} from '~/flowtype';
} from 'flowtype';
const exclude: Array<string> = [
ADD, OPEN, CLOSE,

View File

@ -3,9 +3,9 @@
import { DEVICE } from 'trezor-connect';
import { LOCATION_CHANGE, push, 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';
import * as CONNECT from 'actions/constants/TrezorConnect';
import * as WALLET from 'actions/constants/wallet';
import * as NotificationActions from 'actions/NotificationActions';
import type {
Middleware,
@ -19,7 +19,7 @@ import type {
GetState,
RouterLocationState,
TrezorDevice,
} from '~/flowtype';
} from 'flowtype';
/**
* Middleware used for init application and managing router path.

View File

@ -6,15 +6,15 @@ import { push } from 'react-router-redux';
import TrezorConnect, {
TRANSPORT, DEVICE_EVENT, UI_EVENT, UI, DEVICE,
} from 'trezor-connect';
import * as TrezorConnectActions from '../actions/TrezorConnectActions';
import * as DiscoveryActions from '../actions/DiscoveryActions';
import * as ModalActions from '../actions/ModalActions';
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 * as TrezorConnectActions from 'actions/TrezorConnectActions';
import * as DiscoveryActions from 'actions/DiscoveryActions';
import * as ModalActions from 'actions/ModalActions';
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,
@ -26,7 +26,7 @@ import type {
AsyncAction,
GetState,
RouterLocationState,
} from '~/flowtype';
} from 'flowtype';
const TrezorConnectService: Middleware = (api: MiddlewareAPI) => (next: MiddlewareDispatch) => (action: Action): Action => {
const prevState: $ElementType<State, 'connect'> = api.getState().connect;

View File

@ -3,24 +3,19 @@
import { DEVICE } from 'trezor-connect';
import { LOCATION_CHANGE } from 'react-router-redux';
import * as WALLET from '../actions/constants/wallet';
import * as SEND from '../actions/constants/wallet';
import * as WALLET from 'actions/constants/wallet';
import * as WalletActions from '../actions/WalletActions';
import * as LocalStorageActions from '../actions/LocalStorageActions';
import * as TrezorConnectActions from '../actions/TrezorConnectActions';
import * as SelectedAccountActions from '../actions/SelectedAccountActions';
import * as WalletActions from 'actions/WalletActions';
import * as LocalStorageActions from 'actions/LocalStorageActions';
import * as TrezorConnectActions from 'actions/TrezorConnectActions';
import * as SelectedAccountActions from 'actions/SelectedAccountActions';
import type {
Middleware,
MiddlewareAPI,
MiddlewareDispatch,
State,
Dispatch,
Action,
GetState,
TrezorDevice,
} from '~/flowtype';
} from 'flowtype';
/**
* Middleware

View File

@ -1,6 +1,3 @@
/* @flow */
import WalletService from './WalletService';
import LogService from './LogService';
import RouterService from './RouterService';

View File

@ -8,13 +8,13 @@ import thunk from 'redux-thunk';
// import { useRouterHistory } from 'react-router';
import createHistory from 'history/createHashHistory';
import { createLogger } from 'redux-logger';
import reducers from '../reducers';
import services from '../services';
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 });

View File

@ -0,0 +1,64 @@
import { injectGlobal } from 'styled-components';
import normalize from 'styled-normalize';
const baseStyles = () => injectGlobal`
${normalize};
html, body {
width: 100%;
height: 100%;
position: relative;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Helvetica Neue", Arial, sans-serif;
font-weight: 400;
font-size: 14px;
}
* , *:before , *:after {
box-sizing: border-box;
}
* {
margin: 0;
padding: 0;
}
*::selection, *::-moz-selection, *:focus, *:active, *:active:focus, {
outline: 0 !important;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
a {
text-decoration: none;
cursor: pointer;
}
a:focus,
button:focus,
input:focus,
textarea:focus {
outline: 0;
}
@font-face {
font-family: 'Roboto Zero';
src: url('../fonts/roboto/RobotoZero.eot') format('embedded-opentype'),
url('../fonts/roboto/RobotoZero.eot?#iefix') format('embedded-opentype'),
url('../fonts/roboto/RobotoZero.woff') format('woff'),
url('../fonts/roboto/RobotoZero.ttf') format('truetype');
}
@font-face {
font-family: 'Roboto Mono';
font-style: normal;
src: url('../fonts/roboto/roboto-mono-v4-greek_cyrillic-ext_greek-ext_latin_cyrillic_vietnamese_latin-ext-regular.eot') format('embedded-opentype'), /* IE9 Compat Modes */
url('../fonts/roboto/roboto-mono-v4-greek_cyrillic-ext_greek-ext_latin_cyrillic_vietnamese_latin-ext-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('../fonts/roboto/roboto-mono-v4-greek_cyrillic-ext_greek-ext_latin_cyrillic_vietnamese_latin-ext-regular.woff2') format('woff2'), /* Super Modern Browsers */
url('../fonts/roboto/roboto-mono-v4-greek_cyrillic-ext_greek-ext_latin_cyrillic_vietnamese_latin-ext-regular.woff') format('woff'), /* Modern Browsers */
url('../fonts/roboto/roboto-mono-v4-greek_cyrillic-ext_greek-ext_latin_cyrillic_vietnamese_latin-ext-regular.ttf') format('truetype'), /* Safari, Android, iOS */
url('../fonts/roboto/roboto-mono-v4-greek_cyrillic-ext_greek-ext_latin_cyrillic_vietnamese_latin-ext-regular.svg#RobotoMono') format('svg'); /* Legacy iOS */
}
`;
export default baseStyles;

View File

@ -0,0 +1,26 @@
import React, { Component } from 'react';
class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
componentDidCatch(error, info) {
// Display fallback UI
this.setState({ hasError: true });
console.error('error', error);
// You can also log the error to an error reporting service
// logErrorToMyService(error, info);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return <div>Something went wrong.</div>;
}
return this.props.children;
}
}
export default ErrorBoundary;

View File

@ -1,6 +1,5 @@
/* @flow */
import BigNumber from 'bignumber.js';
export const decimalToHex = (dec: number): string => new BigNumber(dec).toString(16);

View File

@ -10,9 +10,9 @@ export const httpRequest = async (url: string, type: string = 'text'): any => {
const txt: string = await response.text();
return JSON.parse(txt);
} if (type === 'binary') {
return await response.arrayBuffer();
await response.arrayBuffer();
}
return await response.text();
await response.text();
}
throw new Error(`${url} ${response.statusText}`);

View File

@ -5,7 +5,7 @@
// import Promise from 'es6-promise';
export async function resolveAfter<T>(msec: number, value: any = null): Promise<T> {
return await new Promise((resolve) => {
await new Promise((resolve) => {
//root.setTimeout(resolve, msec, value);
window.setTimeout(resolve, msec, value);
});

View File

@ -1,14 +1,12 @@
/* @flow */
import React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import LandingPage from './LandingPage';
import type { MapStateToProps, MapDispatchToProps } from 'react-redux';
import type { State, Dispatch } from '~/flowtype';
import type { State, Dispatch } from 'flowtype';
import LandingPage from './index';
export type StateProps = {
localStorage: $ElementType<State, 'localStorage'>,
@ -38,7 +36,6 @@ const mapStateToProps: MapStateToProps<State, OwnProps, StateProps> = (state: St
wallet: state.wallet,
connect: state.connect,
router: state.router,
wallet: state.wallet,
devices: state.devices,
});

View File

@ -0,0 +1,32 @@
import React from 'react';
import { H2 } from 'components/Heading';
const ConnectHIDDevice = () => (
<main>
<H2 claim>The private bank in your hands.</H2>
<p>TREZOR Wallet is an easy-to-use interface for your TREZOR.</p>
<p>TREZOR Wallet allows you to easily control your funds, manage your balance and initiate transfers.</p>
<div className="row">
<p className="connect">
<span>
<svg width="12px" height="35px" viewBox="0 0 20 57">
<g stroke="none" strokeWidth="1" fill="none" transform="translate(1, 1)">
<rect className="connect-usb-pin" fill="#01B757" x="6" y="39" width="6" height="5" />
<rect className="connect-usb-cable" stroke="#01B757" strokeWidth="1" x="8.5" y="44.5" width="1" height="11" />
<path stroke="#01B757" d="M8.90856859,33.9811778 L6.43814432,33.9811778 C5.45301486,34.0503113 4.69477081,33.6889084 4.1634122,32.8969691 C3.36637428,31.7090602 -0.000402169348,26.3761977 0.0748097911,23.2982514 C0.124878873,21.2492429 0.0999525141,14.5598149 3.07156595e-05,3.22996744 C-0.000274213164,3.1963928 0.00243636275,3.162859 0.00812115776,3.12976773 C0.28477346,1.51937083 1.22672004,0.617538852 2.8339609,0.424271782 C4.45813658,0.228968338 6.54411954,0.0875444105 9.09190977,0 L9.09190977,0.0169167084 C11.5566027,0.104886477 13.5814718,0.244169993 15.1665175,0.434768145 C16.7530267,0.625542287 17.6912941,1.50671985 17.9813196,3.07830083 C17.9943481,3.14889902 18.0005888,3.22058224 17.9999563,3.29236974 L17.9999901,3.29237004 C17.9004498,14.5907444 17.875676,21.2628703 17.9256686,23.3087478 C18.0008805,26.3866941 14.6341041,31.7195566 13.8370662,32.9074655 C13.3057075,33.6994047 12.5474635,34.0608076 11.562334,33.9916742 L8.90856859,33.9916742 L8.90856859,33.9811778 Z" />
<rect fill="#01B757" x="2" y="7" width="14" height="7" rx="0.5625" />
</g>
</svg>
Connect TREZOR to continue
</span>
</p>
</div>
<div className="image">
<p>
<span>Don't have TREZOR? <a href="https://trezor.io/" className="green" target="_blank" rel="noreferrer noopener">Get one</a></span>
</p>
</div>
</main>
);
export default ConnectHIDDevice;

View File

@ -0,0 +1,48 @@
import React, { Component } from 'react';
import { H2 } from 'components/Heading';
import TrezorConnect from 'trezor-connect';
class ConnectWebUsbDevice extends Component<Props> {
componentDidMount() {
TrezorConnect.renderWebUSBButton();
}
componentDidUpdate() {
TrezorConnect.renderWebUSBButton();
}
render() {
return (
<main>
<H2 claim>The private bank in your hands.</H2>
<p>TREZOR Wallet is an easy-to-use interface for your TREZOR.</p>
<p>TREZOR Wallet allows you to easily control your funds, manage your balance and initiate transfers.</p>
<div className="row webusb">
<p className="connect">
<span>
<svg width="12px" height="35px" viewBox="0 0 20 57">
<g stroke="none" strokeWidth="1" fill="none" transform="translate(1, 1)">
<rect className="connect-usb-pin" fill="#01B757" x="6" y="39" width="6" height="5" />
<rect className="connect-usb-cable" stroke="#01B757" strokeWidth="1" x="8.5" y="44.5" width="1" height="11" />
<path stroke="#01B757" d="M8.90856859,33.9811778 L6.43814432,33.9811778 C5.45301486,34.0503113 4.69477081,33.6889084 4.1634122,32.8969691 C3.36637428,31.7090602 -0.000402169348,26.3761977 0.0748097911,23.2982514 C0.124878873,21.2492429 0.0999525141,14.5598149 3.07156595e-05,3.22996744 C-0.000274213164,3.1963928 0.00243636275,3.162859 0.00812115776,3.12976773 C0.28477346,1.51937083 1.22672004,0.617538852 2.8339609,0.424271782 C4.45813658,0.228968338 6.54411954,0.0875444105 9.09190977,0 L9.09190977,0.0169167084 C11.5566027,0.104886477 13.5814718,0.244169993 15.1665175,0.434768145 C16.7530267,0.625542287 17.6912941,1.50671985 17.9813196,3.07830083 C17.9943481,3.14889902 18.0005888,3.22058224 17.9999563,3.29236974 L17.9999901,3.29237004 C17.9004498,14.5907444 17.875676,21.2628703 17.9256686,23.3087478 C18.0008805,26.3866941 14.6341041,31.7195566 13.8370662,32.9074655 C13.3057075,33.6994047 12.5474635,34.0608076 11.562334,33.9916742 L8.90856859,33.9916742 L8.90856859,33.9811778 Z" />
<rect fill="#01B757" x="2" y="7" width="14" height="7" rx="0.5625" />
</g>
</svg>
Connect TREZOR
</span>
</p>
<p className="webusb-and">and</p>
<button className="trezor-webusb-button">Check for devices</button>
</div>
<div className="image">
<p>
<span>Device not recognized? <a href="#/bridge" className="green">Try installing the TREZOR Bridge.</a></span>
<span>Don't have TREZOR? <a href="https://trezor.io/" className="green" target="_blank" rel="noreferrer noopener">Get one</a></span>
</p>
</div>
</main>
);
}
}
export default ConnectWebUsbDevice;

View File

@ -0,0 +1,25 @@
import React from 'react';
import PropTypes from 'prop-types';
import { H2 } from 'components/Heading';
const DisconnectDevice = ({ label }) => (
<main>
<H2 claim>The private bank in your hands.</H2>
<p>TREZOR Wallet is an easy-to-use interface for your TREZOR.</p>
<p>TREZOR Wallet allows you to easily control your funds, manage your balance and initiate transfers.</p>
<div className="row">
<p className="connect">
<span>
Unplug { label } device.
</span>
</p>
</div>
<div className="image" />
</main>
);
DisconnectDevice.propTypes = {
label: PropTypes.string.isRequired,
};
export default DisconnectDevice;

View File

@ -0,0 +1,28 @@
/* @flow */
import React, { Component } from 'react';
import TrezorConnect from 'trezor-connect';
import { H2 } from 'components/Heading';
import type { State, TrezorDevice } from 'flowtype';
import DisconnectDevice from './components/DisconnectDevice';
import ConnectHIDDevice from './components/ConnectHIDDevice';
import ConnectWebUsbDevice from './components/ConnectWebUsbDevice';
type Props = {
transport: $PropertyType<$ElementType<State, 'connect'>, 'transport'>;
disconnectRequest: ?TrezorDevice;
}
const ConnectDevice = (props: Props) => {
const { transport, disconnectRequest } = props;
if (disconnectRequest) {
return <DisconnectDevice label={props.disconnectRequest.label} />;
} if (transport && transport.version.indexOf('webusb') >= 0) {
return <ConnectWebUsbDevice {...props} />;
}
return <ConnectHIDDevice {...props} />;
};
export default ConnectDevice;

View File

@ -1,6 +1,6 @@
/* @flow */
import installers from 'constants/bridge';
import React, { Component } from 'react';
import Select from 'react-select';
import Preloader from './Preloader';
@ -17,15 +17,6 @@ type InstallTarget = {
label: string;
}
const installers: Array<InstallTarget> = [
{ id: 'Windows', value: 'trezor-bridge-2.0.11-win32-install.exe', label: 'Windows' },
{ id: 'macOS', value: 'trezor-bridge-2.0.11.pkg', label: 'Mac OS X' },
{ id: 'Linux', value: 'trezor-bridge_2.0.11_amd64.deb', label: 'Linux 64-bit (deb)' },
{ id: 'Linux-rpm', value: 'trezor-bridge_2.0.11_amd64.rpm', label: 'Linux 64-bit (rpm)' },
{ id: '01', value: 'trezor-bridge_2.0.11_amd32.deb', label: 'Linux 32-bit (deb)' },
{ id: '02', value: 'trezor-bridge_2.0.11_amd32.rpm', label: 'Linux 32-bit (rpm)' },
];
// import type { Props } from './index';
type Props = {
@ -46,12 +37,6 @@ export default class InstallBridge extends Component<Props, State> {
};
}
onChange(value: InstallTarget) {
this.setState({
target: value,
});
}
componentWillUpdate() {
if (this.props.browserState.osname && !this.state.target) {
const currentTarget: ?InstallTarget = installers.find(i => i.id === this.props.browserState.osname);
@ -61,6 +46,12 @@ export default class InstallBridge extends Component<Props, State> {
}
}
onChange(value: InstallTarget) {
this.setState({
target: value,
});
}
render() {
if (!this.state.target) {
return <Preloader />;

View File

@ -2,7 +2,7 @@
import React from 'react';
import Loader from '../common/LoaderCircle';
import Loader from 'components/LoaderCircle';
export default (props: {}): React$Element<string> => (
<section className="landing">

View File

@ -1,22 +1,23 @@
/* @flow */
import React from 'react';
import Preloader from './Preloader';
import ConnectDevice from './ConnectDevice';
import InstallBridge from './InstallBridge';
import LocalStorageError from './LocalStorageError';
import TrezorConnectError from './TrezorConnectError';
import Header from '../common/Header';
import Footer from '../common/Footer';
import Log from '../common/Log';
import Notifications, { Notification } from '../common/Notification';
import { H2 } from 'components/Heading';
import Header from 'components/Header';
import Footer from 'components/Footer';
import Log from 'components/Log';
import Notifications, { Notification } from 'components/Notification';
import Preloader from './components/Preloader';
import ConnectDevice from './components/ConnectDevice';
import InstallBridge from './components/InstallBridge';
import LocalStorageError from './components/LocalStorageError';
import TrezorConnectError from './components/TrezorConnectError';
import type { Props } from './index';
const BrowserNotSupported = (props: {}): React$Element<string> => (
<main>
<h2>Your browser is not supported</h2>
<H2>Your browser is not supported</H2>
<p>Please choose one of the supported browsers</p>
<div className="row">
<div className="chrome">
@ -33,7 +34,7 @@ const BrowserNotSupported = (props: {}): React$Element<string> => (
export default (props: Props) => {
const web3 = props.web3;
const { web3 } = props;
const { devices } = props;
const { browserState, transport } = props.connect;
const localStorageError = props.localStorage.error;

View File

View File

View File

@ -1,48 +1,21 @@
/* @flow */
import React, { Component, PropTypes } from 'react';
import { toggleDeviceDropdown } from 'actions/WalletActions';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import * as TrezorConnectActions from '~/js/actions/TrezorConnectActions';
import { toggleDeviceDropdown } from '~/js/actions/WalletActions';
import Aside from './Aside';
import * as TrezorConnectActions from 'actions/TrezorConnectActions';
import type { MapStateToProps, MapDispatchToProps } from 'react-redux';
import type { State, Dispatch } from '~/flowtype';
import type { State, Dispatch } from 'flowtype';
import type { StateProps, DispatchProps } from './common';
import LeftNavigation from './index';
type OwnProps = {
}
type StateProps = {
connect: $ElementType<State, 'connect'>,
accounts: $ElementType<State, 'accounts'>,
router: $ElementType<State, 'router'>,
deviceDropdownOpened: boolean,
fiat: $ElementType<State, 'fiat'>,
localStorage: $ElementType<State, 'localStorage'>,
discovery: $ElementType<State, 'discovery'>,
wallet: $ElementType<State, 'wallet'>,
devices: $ElementType<State, 'devices'>,
pending: $ElementType<State, 'pending'>,
}
type DispatchProps = {
toggleDeviceDropdown: typeof toggleDeviceDropdown,
addAccount: typeof TrezorConnectActions.addAccount,
acquireDevice: typeof TrezorConnectActions.acquire,
forgetDevice: typeof TrezorConnectActions.forget,
duplicateDevice: typeof TrezorConnectActions.duplicateDevice,
gotoDeviceSettings: typeof TrezorConnectActions.gotoDeviceSettings,
onSelectDevice: typeof TrezorConnectActions.onSelectDevice,
}
export type Props = StateProps & DispatchProps;
const mapStateToProps: MapStateToProps<State, OwnProps, StateProps> = (state: State, own: OwnProps): StateProps => ({
connect: state.connect,
accounts: state.accounts,
@ -67,7 +40,6 @@ const mapDispatchToProps: MapDispatchToProps<Dispatch, OwnProps, DispatchProps>
onSelectDevice: bindActionCreators(TrezorConnectActions.onSelectDevice, dispatch),
});
// export default connect(mapStateToProps, mapDispatchToProps)(Aside);
export default withRouter(
connect(mapStateToProps, mapDispatchToProps)(Aside),
);
connect(mapStateToProps, mapDispatchToProps)(LeftNavigation),
);

View File

@ -0,0 +1,315 @@
/* @flow */
import React, { Component } from 'react';
import BigNumber from 'bignumber.js';
import Icon from 'components/Icon';
import colors from 'config/colors';
import Loader from 'components/LoaderCircle';
import PropTypes from 'prop-types';
import styled, { css } from 'styled-components';
import * as stateUtils from 'reducers/utils';
import Tooltip from 'rc-tooltip';
import ICONS from 'config/icons';
import { NavLink } from 'react-router-dom';
import { findDeviceAccounts } from 'reducers/AccountsReducer';
import {
FONT_SIZE, BORDER_WIDTH, TRANSITION_TIME,
} from 'config/variables';
import type { Accounts } from 'flowtype';
import type { Props } from '../common';
import Row from '../Row';
import RowCoin from '../RowCoin';
const Wrapper = styled.div``;
const Text = styled.span`
font-size: ${FONT_SIZE.SMALLER};
color: ${colors.TEXT_SECONDARY};
`;
const RowAccountWrapper = styled.div`
height: 64px;
padding: 16px 0 16px 24px;
font-size: ${FONT_SIZE.SMALL};
color: ${colors.TEXT_PRIMARY};
border-top: 1px solid ${colors.DIVIDER};
&:hover {
background-color: ${colors.GRAY_LIGHT};
}
${props => props.isSelected && css`
border-left: ${BORDER_WIDTH.SELECTED} solid ${colors.GREEN_PRIMARY};
background: ${colors.WHITE};
&:hover {
background-color: ${colors.WHITE};
}
&:last-child {
border-bottom: 1px solid ${colors.DIVIDER};
}
`}
`;
const RowAccount = ({
accountIndex, balance, isSelected = false,
}) => (
<RowAccountWrapper
isSelected={isSelected}
>
<Row column>
Account #{accountIndex + 1}
{balance ? (
<Text>{balance}</Text>
) : (
<Text>Loading...</Text>
)}
</Row>
</RowAccountWrapper>
);
RowAccount.propTypes = {
accountIndex: PropTypes.number.isRequired,
balance: PropTypes.string,
isSelected: PropTypes.bool,
};
const AddAccountWrapper = styled.div`
position: relative;
padding: 8px 0 8px 20px;
cursor: pointer;
color: ${colors.TEXT_SECONDARY};
display: flex;
align-items: center;
&:hover {
color: ${colors.TEXT_PRIMARY};
transition: background-color ${TRANSITION_TIME.BASE} ease-in-out, color ${TRANSITION_TIME.BASE} ease-in-out, border-color ${TRANSITION_TIME.BASE} ease-in-out;
}
`;
const AddAccountIconWrapper = styled.div`
margin-right: 12px;
`;
const DiscoveryStatusWrapper = styled.div`
height: 64px;
display: flex;
flex-direction: column;
justify-content: space-evenly;
font-size: ${FONT_SIZE.SMALL};
padding: 16px 28px 16px 30px;
white-space: nowrap;
border-top: 1px solid ${colors.DIVIDER};
`;
const DiscoveryStatusText = styled.div`
display: block;
font-size: ${FONT_SIZE.SMALLER};
color: ${colors.TEXT_SECONDARY};
overflow: hidden;
text-overflow: ellipsis;
`;
const DiscoveryLoadingWrapper = styled.div`
display: flex;
flex-direction: row;
align-items: center;
font-size: ${FONT_SIZE.SMALL};
padding: 8px 0 8px 22px;
white-space: nowrap;
color: ${colors.TEXT_SECONDARY};
`;
const DiscoveryLoadingText = styled.span`
margin-left: 14px;
`;
// class AccountMenu extends Component {
// constructor(props: Props) {
// super(props);
// this.state = {
// selectedAccounts: null,
// selectedCoin: null,
// };
// }
// componentWillReceiveProps(nextProps) {
// }
// render() {
// return (
// <div>
// Hello
// </div>
// );
// }
// }
const AccountMenu = (props: Props): ?React$Element<string> => {
const selected = props.wallet.selectedDevice;
const { location } = props.router;
const urlParams = location.state;
const { accounts } = props;
const baseUrl: string = urlParams.deviceInstance ? `/device/${urlParams.device}:${urlParams.deviceInstance}` : `/device/${urlParams.device}`;
const { config } = props.localStorage;
const selectedCoin = config.coins.find(c => c.network === location.state.network);
const fiatRate = props.fiat.find(f => f.network === selectedCoin.network);
const deviceAccounts: Accounts = findDeviceAccounts(accounts, selected, location.state.network);
let selectedAccounts = deviceAccounts.map((account, i) => {
// const url: string = `${baseUrl}/network/${location.state.network}/account/${i}`;
const url: string = location.pathname.replace(/account+\/([0-9]*)/, `account/${i}`);
let balance: string = 'Loading...';
if (account.balance !== '') {
const pending = stateUtils.getAccountPendingTx(props.pending, account);
const pendingAmount: BigNumber = stateUtils.getPendingAmount(pending, selectedCoin.symbol);
const availableBalance: string = new BigNumber(account.balance).minus(pendingAmount).toString(10);
if (fiatRate) {
const accountBalance = new BigNumber(availableBalance);
const fiat = accountBalance.times(fiatRate.value).toFixed(2);
balance = `${availableBalance} ${selectedCoin.symbol} / $${fiat}`;
} else {
balance = `${availableBalance} ${selectedCoin.symbol}`;
}
}
const urlAccountIndex = parseInt(props.router.location.state.account, 10);
return (
<NavLink
to={url}
key={account.index}
>
<RowAccount
accountIndex={account.index}
url={url}
balance={balance}
isSelected={urlAccountIndex === account.index}
/>
</NavLink>
);
});
if (selectedAccounts.length < 1) {
if (selected.connected) {
const url: string = location.pathname.replace(/account+\/([0-9]*)/, 'account/0');
selectedAccounts = (
<NavLink
to={url}
>
<RowAccount
accountIndex={0}
url={url}
isSelected
/>
</NavLink>
);
}
}
let discoveryStatus = null;
const discovery = props.discovery.find(d => d.deviceState === selected.state && d.network === location.state.network);
if (discovery) {
if (discovery.completed) {
// TODO: add only if last one is not empty
//if (selectedAccounts.length > 0 && selectedAccounts[selectedAccounts.length - 1])
const lastAccount = deviceAccounts[deviceAccounts.length - 1];
if (lastAccount && (new BigNumber(lastAccount.balance).greaterThan(0) || lastAccount.nonce > 0)) {
discoveryStatus = (
<AddAccountWrapper
onClick={props.addAccount}
>
<AddAccountIconWrapper>
<Icon
icon={ICONS.PLUS}
size={24}
color={colors.TEXT_SECONDARY}
/>
</AddAccountIconWrapper>
Add account
</AddAccountWrapper>
);
} else {
const tooltip = (
<div className="aside-tooltip-wrapper">
To add a new account, last account must have some transactions.
</div>
);
discoveryStatus = (
<Tooltip
arrowContent={<div className="rc-tooltip-arrow-inner" />}
overlay={tooltip}
placement="top"
>
<div className="add-account disabled">
Add account
</div>
</Tooltip>
);
}
} else if (!selected.connected || !selected.available) {
discoveryStatus = (
<DiscoveryStatusWrapper>
Accounts could not be loaded
<DiscoveryStatusText>
{`Connect ${selected.instanceLabel} device`}
</DiscoveryStatusText>
</DiscoveryStatusWrapper>
);
} else {
discoveryStatus = (
<DiscoveryLoadingWrapper>
<Loader size="20" />
<DiscoveryLoadingText>
Loading accounts...
</DiscoveryLoadingText>
</DiscoveryLoadingWrapper>
);
}
}
let backButton = null;
if (selectedCoin) {
let imgName = selectedCoin.network;
if (selectedCoin.network === 'ethereum') {
imgName = 'eth';
} else if (selectedCoin.network === 'ethereum-classic') {
imgName = 'etc';
}
const imgUrl = `../images/${imgName}-logo.png`;
backButton = (
<NavLink to={baseUrl}>
<RowCoin
coin={{
img: imgUrl,
name: selectedCoin.name,
}}
iconLeft={{
type: ICONS.ARROW_LEFT,
color: colors.TEXT_PRIMARY,
size: 20,
}}
/>
</NavLink>
);
}
return (
<Wrapper>
{backButton}
<div>
{selectedAccounts}
</div>
{discoveryStatus}
</Wrapper>
);
};
export default AccountMenu;

View File

@ -0,0 +1,87 @@
import styled from 'styled-components';
import coins from 'constants/coins';
import colors from 'config/colors';
import ICONS from 'config/icons';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { NavLink } from 'react-router-dom';
import Divider from '../Divider';
import RowCoin from '../RowCoin';
const Wrapper = styled.div``;
class CoinMenu extends Component {
getBaseUrl() {
const { selectedDevice } = this.props.wallet;
let baseUrl = '';
if (selectedDevice && selectedDevice.features) {
baseUrl = `/device/${selectedDevice.features.device_id}`;
if (selectedDevice.instance) {
baseUrl += `:${selectedDevice.instance}`;
}
}
return baseUrl;
}
getImgUrl(network) {
let imgName = network;
if (network === 'ethereum') {
imgName = 'eth';
} else if (network === 'ethereum-classic') {
imgName = 'etc';
}
return `../images/${imgName}-logo.png`;
}
render() {
const { config } = this.props.localStorage;
return (
<Wrapper>
{config.coins.map(item => (
<NavLink
key={item.network}
to={`${this.getBaseUrl()}/network/${item.network}/account/0`}
>
<RowCoin
coin={{
img: this.getImgUrl(item.network),
name: item.name,
}}
/>
</NavLink>
))}
<Divider
textLeft="Other coins"
textRight="(You will be redirected)"
borderTop
borderBottom
/>
{coins.map(coin => (
<a key={coin.url} href={coin.url}>
<RowCoin
coin={{
img: coin.image,
name: coin.coinName,
}}
iconRight={{
type: ICONS.SKIP,
color: colors.TEXT_SECONDARY,
size: 27,
}}
/>
</a>
))}
</Wrapper>
);
}
}
CoinMenu.propTypes = {
config: PropTypes.object,
wallet: PropTypes.object,
selectedDevice: PropTypes.object,
localStorage: PropTypes.object,
};
export default CoinMenu;

View File

@ -0,0 +1,47 @@
import React from 'react';
import styled from 'styled-components';
import deviceConstants from 'constants/device';
const Wrapper = styled.div``;
class DeviceList {
getStatus(device) {
let deviceStatus = '';
if (device.type === 'unacquired' || (device.features && device.status === 'occupied')) {
deviceStatus = 'Used in other window';
} else if (device.type === 'unreadable') {
deviceStatus = 'Connected';
} else if (!device.connected) {
deviceStatus = 'Disconnected';
} else if (!device.available) {
deviceStatus = 'Unavailable';
}
return deviceStatus;
}
render() {
return (
<Wrapper>
{this.props.devices.map((device, index) => (
<div key={index} className={css} onClick={() => this.props.onSelectDevice(device)}>
<div className="label-container">
<span className="label">{device.instanceLabel}</span>
<span className="status">{this.getStatus(device)}</span>
</div>
<div
className="forget-button"
onClick={(event) => {
event.stopPropagation();
event.preventDefault();
this.onDeviceMenuClick({ type: 'forget', label: '' }, device);
}}
/>
</div>
))}
</Wrapper>
);
}
}
export default DeviceList;

Some files were not shown because too many files have changed in this diff Show More