From 1c89f3e9757e344c7f91b04e3d18b924351ba00e Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Sat, 5 May 2018 13:52:03 +0200 Subject: [PATCH] before testing --- .flowconfig | 3 + src/data/appConfig.json | 43 +++----- src/js/actions/LogActions.js | 22 ++++- src/js/actions/ReceiveActions.js | 3 +- src/js/actions/SendFormActions.js | 15 ++- src/js/actions/TrezorConnectActions.js | 10 +- src/js/actions/Web3Actions.js | 29 +++--- src/js/actions/constants/log.js | 3 +- src/js/components/common/Log.js | 8 +- src/js/components/landing/ConnectDevice.js | 99 ++++++++++++++----- src/js/components/landing/InstallBridge.js | 3 +- src/js/components/landing/LandingPage.js | 3 +- src/js/components/modal/ConfirmAddress.js | 34 ++++--- src/js/components/modal/DuplicateDevice.js | 4 +- src/js/components/modal/RememberDevice.js | 31 +++--- src/js/components/modal/index.js | 8 +- src/js/components/wallet/Acquire.js | 2 +- src/js/components/wallet/Receive.js | 13 +-- .../wallet/account/AbstractAccount.js | 8 +- .../wallet/aside/AccountSelection.js | 2 - .../components/wallet/aside/CoinSelection.js | 5 +- .../wallet/aside/DeviceSelection.js | 21 ++-- .../wallet/aside/StickyContainer.js | 1 - .../wallet/send/PendingTransactions.js | 2 +- src/js/components/wallet/send/SendForm.js | 10 +- src/js/components/wallet/summary/Summary.js | 8 +- .../wallet/summary/SummaryDetails.js | 7 +- .../wallet/summary/SummaryTokens.js | 6 +- src/js/components/wallet/summary/index.js | 6 +- src/js/flowtype/bignumber.js | 55 +++++++++++ src/js/flowtype/ethereum-types.js | 72 ++++++++++++++ src/js/flowtype/trezor-connect.js | 6 +- src/js/flowtype/web3.js | 80 ++++++++++++++- src/js/reducers/AbstractAccountReducer.js | 5 +- src/js/reducers/LocalStorageReducer.js | 10 +- src/js/reducers/LogReducer.js | 18 ++-- src/js/reducers/ModalReducer.js | 2 - src/js/reducers/TrezorConnectReducer.js | 26 +++-- src/js/reducers/WalletReducer.js | 24 ++++- src/js/services/LogService.js | 40 ++++++++ src/js/services/TrezorConnectService.js | 7 +- src/js/services/index.js | 2 + src/js/store/index.js | 51 +++++----- src/styles/log.less | 1 + src/styles/summary.less | 3 +- 45 files changed, 577 insertions(+), 234 deletions(-) create mode 100644 src/js/flowtype/bignumber.js create mode 100644 src/js/flowtype/ethereum-types.js create mode 100644 src/js/services/LogService.js diff --git a/.flowconfig b/.flowconfig index 59038724..ef1b624c 100644 --- a/.flowconfig +++ b/.flowconfig @@ -18,6 +18,9 @@ ./src/js/flowtype/react-router-redux.js ./src/js/flowtype/css.js ./src/js/flowtype/trezor-connect.js +./src/js/flowtype/bignumber.js +./src/js/flowtype/ethereum-types.js +./src/js/flowtype/web3.js [options] diff --git a/src/data/appConfig.json b/src/data/appConfig.json index 7578c0cf..cb48d70b 100644 --- a/src/data/appConfig.json +++ b/src/data/appConfig.json @@ -1,27 +1,4 @@ { - "coins1": [ - { - "name": "Ethereum Ropsten", - "symbol": "eth", - "network": "ropsten-eth", - "shortcut": "eth", - "bip44": "m/44'/60'/0'/0", - "defaultGasPrice": 64, - "defaultGasLimit": 21000, - "defaultGasLimitTokens": 200000, - "backends": [ - { - "name": "TREZOR Wallet - Ethereum", - "urls": [ - "https://ropsten.infura.io/QGyVKozSUEh2YhL4s2G4", - "http://10.34.2.5:8545" - ], - "explorer": "https://blockexplorer.com" - } - ] - } - ], - "coins": [ { "name": "Ethereum", @@ -41,7 +18,10 @@ ] } ], - "explorer": "https://etherscan.io" + "explorer": { + "tx": "https://etherscan.io/tx/", + "address": "https://etherscan.io/address/" + } }, { "name": "Ethereum Classic", @@ -63,7 +43,10 @@ ] } ], - "explorer": "https://etherscan.io" + "explorer": { + "tx": "https://gastracker.io/tx/", + "address": "https://gastracker.io/addr/" + } }, { "name": "Ethereum Ropsten", @@ -83,7 +66,10 @@ ] } ], - "explorer": "https://ropsten.etherscan.io" + "explorer": { + "tx": "https://ropsten.etherscan.io/tx/", + "address": "https://ropsten.etherscan.io/tx/" + } }, { "name": "Ethereum Rinkeby", @@ -102,7 +88,10 @@ ] } ], - "explorer": "https://rinkeby.etherscan.io" + "explorer": { + "tx": "https://rinkeby.etherscan.io/tx/", + "tx": "https://rinkeby.etherscan.io/address/" + } } ], diff --git a/src/js/actions/LogActions.js b/src/js/actions/LogActions.js index b8131795..9409c5ca 100644 --- a/src/js/actions/LogActions.js +++ b/src/js/actions/LogActions.js @@ -3,12 +3,16 @@ import * as LOG from './constants/log'; -import type { ThunkAction, GetState, Dispatch } from '../flowtype'; +import type { Action, ThunkAction, GetState, Dispatch } from '../flowtype'; +import type { LogEntry } from '../reducers/LogReducer'; export type LogAction = { type: typeof LOG.OPEN, } | { type: typeof LOG.CLOSE, +} | { + type: typeof LOG.ADD, + payload: LogEntry }; export const toggle = (): ThunkAction => { @@ -18,12 +22,24 @@ export const toggle = (): ThunkAction => { window.scrollTo(0, 0); dispatch({ - type: LOG.CLOSE + type: LOG.OPEN }); } else { dispatch({ - type: LOG.OPEN + type: LOG.CLOSE }); } } } + +// export const add = (type: string, message: string): Action => { +export const add = (type: string, message: any): Action => { + return { + type: LOG.ADD, + payload: { + time: new Date().getTime(), + type, + message + } + } +} diff --git a/src/js/actions/ReceiveActions.js b/src/js/actions/ReceiveActions.js index a48cf9a4..6e4ab0ed 100644 --- a/src/js/actions/ReceiveActions.js +++ b/src/js/actions/ReceiveActions.js @@ -66,7 +66,8 @@ export const showUnverifiedAddress = (): Action => { } } -export const showAddress = (address_n: string): AsyncAction => { +//export const showAddress = (address_n: string): AsyncAction => { +export const showAddress = (address_n: Array): AsyncAction => { return async (dispatch: Dispatch, getState: GetState): Promise => { const selected = findSelectedDevice(getState().connect); diff --git a/src/js/actions/SendFormActions.js b/src/js/actions/SendFormActions.js index 323b8edb..2d1eb15f 100644 --- a/src/js/actions/SendFormActions.js +++ b/src/js/actions/SendFormActions.js @@ -118,10 +118,10 @@ const getMaxAmount = () => { } export const getFeeLevels = (symbol: string, gasPrice: BigNumber | string, gasLimit: string): Array => { - if (typeof gasPrice === 'string') gasPrice = new BigNumber(gasPrice); - const quarter: BigNumber = gasPrice.dividedBy(4); - const high: string = gasPrice.plus(quarter.times(2)).toString(); - const low: string = gasPrice.minus(quarter.times(2)).toString(); + const price: BigNumber = typeof gasPrice === 'string' ? new BigNumber(gasPrice) : gasPrice + const quarter: BigNumber = price.dividedBy(4); + const high: string = price.plus(quarter.times(2)).toString(); + const low: string = price.minus(quarter.times(2)).toString(); return [ { @@ -132,7 +132,7 @@ export const getFeeLevels = (symbol: string, gasPrice: BigNumber | string, gasLi { value: 'Normal', gasPrice: gasPrice.toString(), - label: `${ calculateFee(gasPrice.toString(), gasLimit) } ${ symbol }` + label: `${ calculateFee(price.toString(), gasLimit) } ${ symbol }` }, { value: 'Low', @@ -798,8 +798,6 @@ export const onSend = (): AsyncAction => { // txData.gasLimit = web3.toHex(gasLimit); // txData.gasPrice = web3.toHex( EthereumjsUnits.convert(gasPrice, 'gwei', 'wei') ); - // console.log("---->GASSS", txData, gasLimit, gasPrice, EthereumjsUnits.convert(gasPrice, 'gwei', 'wei')); - const selected: ?TrezorDevice = findSelectedDevice(getState().connect); if (!selected) return; @@ -840,7 +838,6 @@ export const onSend = (): AsyncAction => { txData.v = web3.toHex(signedTransaction.payload.v); // const gasLimit2 = await estimateGas(web3, txData); - // console.log("---->GASSS", txData, gasLimit2.toString() ); const { config } = getState().localStorage; if (!config) return; @@ -866,7 +863,7 @@ export const onSend = (): AsyncAction => { payload: { type: 'success', title: 'Transaction success', - message: `See transaction detail`, + message: `See transaction detail`, cancelable: true, actions: [] } diff --git a/src/js/actions/TrezorConnectActions.js b/src/js/actions/TrezorConnectActions.js index d291ce9e..92073e53 100644 --- a/src/js/actions/TrezorConnectActions.js +++ b/src/js/actions/TrezorConnectActions.js @@ -135,10 +135,10 @@ export const init = (): AsyncAction => { webusb: true }); } catch (error) { - dispatch({ - type: CONNECT.INITIALIZATION_ERROR, - error - }) + // dispatch({ + // type: CONNECT.INITIALIZATION_ERROR, + // error + // }) } } } @@ -227,7 +227,6 @@ export const onSelectDevice = (device: TrezorDevice | Device): ThunkAction => { // || device.isUsedElsewhere // switch to initial url and reset this value - console.warn("ON SELECT DEV d", device); if (!device.features) { dispatch( push(`/device/${ device.path }/acquire`) ); @@ -295,7 +294,6 @@ export const switchToFirstAvailableDevice = (): AsyncAction => { export const getSelectedDeviceState = (): AsyncAction => { return async (dispatch: Dispatch, getState: GetState): Promise => { const selected = findSelectedDevice(getState().connect); - console.warn("init selected", selected) if (selected && selected.connected && selected.features diff --git a/src/js/actions/Web3Actions.js b/src/js/actions/Web3Actions.js index 283d98e8..f1b67f25 100644 --- a/src/js/actions/Web3Actions.js +++ b/src/js/actions/Web3Actions.js @@ -1,7 +1,7 @@ /* @flow */ 'use strict'; -import Web3, { ContractFactory, Contract } from 'web3'; +import Web3 from 'web3'; import HDKey from 'hdkey'; import EthereumjsUtil from 'ethereumjs-util'; import EthereumjsTx from 'ethereumjs-tx'; @@ -21,6 +21,7 @@ import type { import type { Account } from '../reducers/AccountsReducer'; import type { PendingTx } from '../reducers/PendingTxReducer'; +import type { Web3Instance } from '../reducers/Web3Reducer'; export type Web3Action = { type: typeof WEB3.READY, @@ -31,7 +32,7 @@ export type Web3Action = { export type Web3CreateAction = { type: typeof WEB3.CREATE, network: string, - web3: any, //(web3instance) + web3: Web3, //(web3instance) erc20: any, chainId: string; }; @@ -45,7 +46,7 @@ export type Web3UpdateBlockAction = { export type Web3UpdateGasPriceAction = { type: typeof WEB3.GAS_PRICE_UPDATED, network: string, - gasPrice: any + gasPrice: string }; @@ -94,12 +95,8 @@ export function init(web3: ?Web3, coinIndex: number = 0): AsyncAction { //web3 = new Web3( new Web3.providers.HttpProvider("ws://34.230.234.51:30303") ); // initial check if backend is running - // instance.version.getNetwork(function(error, chainId){ - // if (!error) { - - - instance.eth.getGasPrice((error, gasPrice) => { + instance.eth.getGasPrice((error: Error, gasPrice: string) => { if (error) { // try different url dispatch( init(instance, coinIndex) ); @@ -140,12 +137,12 @@ export function init(web3: ?Web3, coinIndex: number = 0): AsyncAction { const latestBlockFilter = instance.eth.filter('latest'); - const onBlockMined = async (error, blockHash) => { + const onBlockMined = async (error: ?Error, blockHash: ?string) => { if (error) { window.setTimeout(() => { // try again - onBlockMined("manually_triggered_error", undefined); + onBlockMined(new Error("manually_triggered_error"), undefined); }, 30000); } @@ -221,7 +218,6 @@ export function init(web3: ?Web3, coinIndex: number = 0): AsyncAction { // } // contract.decimals.call((error, decimals) => { -// console.log("nameeeee", name, symbol, decimals) // }) // }); @@ -353,7 +349,7 @@ export const getBalanceAsync = (web3: Web3, address: string): Promise => { }); } -export const getTokenBalanceAsync = (erc20: any, token: string, address: string): Promise => { +export const getTokenBalanceAsync = (erc20: any, token: string, address: string): Promise => { return new Promise((resolve, reject) => { const contr = erc20.at(token); @@ -383,26 +379,27 @@ export const getNonceAsync = (web3: Web3, address: string): Promise => { export const getTokenInfoAsync = (erc20: any, address: string): Promise => { return new Promise((resolve, reject) => { - const contract = erc20.at(address); + const contract = erc20.at(address, (error, res) => { + console.warn("callack", error, res) + }); + + console.warn("AT", contract) const info = {}; // TODO: handle errors contract.name.call((e, name) => { if (e) { - //console.log("1", address, e) //resolve(null); //return; } info.name = name; contract.symbol.call((e, symbol) => { if (e) { - console.log("2", e) resolve(null); return; } info.symbol = symbol; contract.decimals.call((e, decimals) => { if (e) { - console.log("3", e) resolve(null); return; } diff --git a/src/js/actions/constants/log.js b/src/js/actions/constants/log.js index de85d8eb..9c33fb60 100644 --- a/src/js/actions/constants/log.js +++ b/src/js/actions/constants/log.js @@ -2,4 +2,5 @@ 'use strict'; export const OPEN: 'log__open' = 'log__open'; -export const CLOSE: 'log__close' = 'log__close'; \ No newline at end of file +export const CLOSE: 'log__close' = 'log__close'; +export const ADD: 'log__add' = 'log__add'; \ No newline at end of file diff --git a/src/js/components/common/Log.js b/src/js/components/common/Log.js index bc927df4..fddd440c 100644 --- a/src/js/components/common/Log.js +++ b/src/js/components/common/Log.js @@ -16,13 +16,19 @@ type Props = { const Log = (props: Props): ?React$Element => { if (!props.log.opened) return null; + + // const entries = props.log.entries.map(entry => { + // return ( + + // ) + // }) return (

Log

Attention: The log contains your XPUBs. Anyone with your XPUBs can see your account history.

- +
) } diff --git a/src/js/components/landing/ConnectDevice.js b/src/js/components/landing/ConnectDevice.js index f8cf87b7..ec0923f4 100644 --- a/src/js/components/landing/ConnectDevice.js +++ b/src/js/components/landing/ConnectDevice.js @@ -4,45 +4,79 @@ import React, { Component } from 'react'; import TrezorConnect from 'trezor-connect'; +import type { State, TrezorDevice } from '../../flowtype'; + type Props = { - transport: any; + transport: $PropertyType<$ElementType, 'transport'>; + disconnectRequest: ?TrezorDevice; } -export default class InstallBridge extends Component { +const DisconnectDevice = (props: Props) => { + if (!props.disconnectRequest) return null; + return ( +
+

The private bank in your hands.

+

TREZOR Wallet is an easy-to-use interface for your TREZOR.

+

TREZOR Wallet allows you to easily control your funds, manage your balance and initiate transfers.

+
+

+ + Unplug { props.disconnectRequest.instanceLabel } device. + +

+
+
+
+
+ ) +} +const ConnectHIDDevice = (props: Props) => { + return ( +
+

The private bank in your hands.

+

TREZOR Wallet is an easy-to-use interface for your TREZOR.

+

TREZOR Wallet allows you to easily control your funds, manage your balance and initiate transfers.

+
+

+ + + + + + + + + + Connect TREZOR to continue + +

+
+
+

+ Don't have TREZOR? Get one +

+
+
+ ); +} + +class ConnectWebUsbDevice extends Component { componentDidMount(): void { - const transport: any = this.props.transport; - if (transport && transport.version.indexOf('webusb') >= 0) - TrezorConnect.renderWebUSBButton(); + TrezorConnect.renderWebUSBButton(); } componentDidUpdate() { - const transport = this.props.transport; - if (transport && transport.version.indexOf('webusb') >= 0) - TrezorConnect.renderWebUSBButton(); + TrezorConnect.renderWebUSBButton(); } render() { - let css = 'row'; - let webusb = null; - let connectClaim = 'Connect TREZOR to continue'; - let and = null; - let bridgeClaim = null; - const transport = this.props.transport; - if (transport && transport.version.indexOf('webusb') >= 0) { - css = 'row webusb' - webusb = ; - connectClaim = 'Connect TREZOR'; - and =

and

; - bridgeClaim = Device not recognized? Try installing the TREZOR Bridge.; - } - return (

The private bank in your hands.

TREZOR Wallet is an easy-to-use interface for your TREZOR.

TREZOR Wallet allows you to easily control your funds, manage your balance and initiate transfers.

-
+

@@ -53,7 +87,7 @@ export default class InstallBridge extends Component { - { connectClaim } + Connect TREZOR

and

@@ -61,11 +95,24 @@ export default class InstallBridge extends Component {

- { bridgeClaim } + Device not recognized? Try installing the TREZOR Bridge. Don't have TREZOR? Get one

); } -} \ No newline at end of file +} + +const ConnectDevice = (props: Props) => { + const { transport, disconnectRequest } = props; + if (disconnectRequest) { + return + } else if (transport && transport.version.indexOf('webusb') >= 0) { + return + } else { + return + } +} + +export default ConnectDevice; \ No newline at end of file diff --git a/src/js/components/landing/InstallBridge.js b/src/js/components/landing/InstallBridge.js index 22507eea..71ad87fd 100644 --- a/src/js/components/landing/InstallBridge.js +++ b/src/js/components/landing/InstallBridge.js @@ -43,7 +43,7 @@ export default class InstallBridge extends Component { this.state = { version: '2.0.12', url: 'https://wallet.trezor.io/data/bridge/2.0.12/', - target: null, + target: currentTarget, }; } @@ -53,7 +53,6 @@ export default class InstallBridge extends Component { }); } - componentWillUpdate() { if (this.props.browserState.osname && !this.state.target) { const currentTarget: ?InstallTarget = installers.find(i => i.id === this.props.browserState.osname); diff --git a/src/js/components/landing/LandingPage.js b/src/js/components/landing/LandingPage.js index 00d11d75..97bb72a1 100644 --- a/src/js/components/landing/LandingPage.js +++ b/src/js/components/landing/LandingPage.js @@ -10,7 +10,6 @@ import TrezorConnectError from './TrezorConnectError'; import Header from '../common/Header'; import Footer from '../common/Footer'; import Log from '../common/Log'; -// import { Notification } from '../common/Notification'; import Notifications, { Notification } from '../common/Notification'; import type { Props } from './index'; @@ -63,7 +62,7 @@ export default (props: Props) => { body = ; } else if (props.wallet.ready && devices.length < 1) { css += ' connect-device'; - body = ; + body = ; } if (notification || body) { diff --git a/src/js/components/modal/ConfirmAddress.js b/src/js/components/modal/ConfirmAddress.js index e314ce71..9a5f8c0b 100644 --- a/src/js/components/modal/ConfirmAddress.js +++ b/src/js/components/modal/ConfirmAddress.js @@ -2,13 +2,16 @@ 'use strict'; import React from 'react'; +import { findAccount } from '../../reducers/AccountsReducer'; import { findSelectedDevice } from '../../reducers/TrezorConnectReducer'; -const ConfirmAddress = (props: any): any => { - - const account = props.accounts.find(a => a.deviceState === props.receive.deviceState && a.index === props.receive.accountIndex && a.network === props.receive.network); - const { config } = props.localStorage; - const selectedCoin = config.coins.find(c => c.network === account.network); +import type { Props } from './index'; + +const ConfirmAddress = (props: Props) => { + + const { accounts, abstractAccount } = props; + const account = findAccount(accounts, abstractAccount.index, abstractAccount.deviceState, abstractAccount.network); + if (!account) return null; return (
@@ -18,16 +21,21 @@ const ConfirmAddress = (props: any): any => {

{ account.address }

- +
); } export default ConfirmAddress; -export const ConfirmUnverifiedAddress = (props: any): any => { +export const ConfirmUnverifiedAddress = (props: Props): any => { + + if (!props.modal.opened) return null; + const { + device + } = props.modal; - const account = props.accounts.find(a => a.deviceState === props.receive.deviceState && a.index === props.receive.accountIndex && a.network === props.receive.network); + const { accounts, abstractAccount } = props; const { onCancel @@ -38,10 +46,9 @@ export const ConfirmUnverifiedAddress = (props: any): any => { showAddress } = props.receiveActions; - const { - device - } = props.modal; - + const account = findAccount(accounts, abstractAccount.index, abstractAccount.deviceState, abstractAccount.network); + if (!account) return null; + if (!device.connected) { return (
@@ -59,7 +66,8 @@ export const ConfirmUnverifiedAddress = (props: any): any => {
); } else { - const enable: string = device.features.passphrase_protection ? 'Enable' : 'Disable'; + // corner-case where device is connected but it is unavailable because it was created with different "passphrase_protection" settings + const enable: string = device.features && device.features.passphrase_protection ? 'Enable' : 'Disable'; return (
diff --git a/src/js/components/modal/DuplicateDevice.js b/src/js/components/modal/DuplicateDevice.js index 236b7a45..3db3375f 100644 --- a/src/js/components/modal/DuplicateDevice.js +++ b/src/js/components/modal/DuplicateDevice.js @@ -2,8 +2,10 @@ 'use strict'; import React from 'react'; +import type { Props } from './index'; -const RememberDevice = (props: any): any => { +const RememberDevice = (props: Props) => { + if (!props.modal.opened) return null; const { device } = props.modal; const { onCancel, onDuplicateDevice } = props.modalActions; return ( diff --git a/src/js/components/modal/RememberDevice.js b/src/js/components/modal/RememberDevice.js index 7c4b8b76..4762fa95 100644 --- a/src/js/components/modal/RememberDevice.js +++ b/src/js/components/modal/RememberDevice.js @@ -67,17 +67,21 @@ export default class RememberDevice extends Component { const { onForgetDevice, onRememberDevice } = this.props.modalActions; let label = device.label; - let devicePlural = false; - if (instances && instances.length > 0) { + let devicePlural: string = "device or to remember it"; + if (instances && instances.length > 1) { label = instances.map((instance, index) => { - return ({instance.instanceLabel}); + let comma: string = ''; + if (index > 0) comma = ', '; + return ( + { comma }{ instance.instanceLabel } + ); }) - devicePlural = instances.length > 1; + devicePlural = "devices or to remember them"; } return (

Forget {label}?

-

Would you like TREZOR Wallet to forget your device or to remember it, so that it is still visible even while disconnected?

+

Would you like TREZOR Wallet to forget your { devicePlural }, so that it is still visible even while disconnected?

@@ -92,22 +96,9 @@ export const ForgetDevice = (props: Props) => { return (

Forget { device.instanceLabel } ?

-

Forgetting only removes the device from the list on the left, your bitcoins are still safe and you can access them by reconnecting your TREZOR again.

- +

Forgetting only removes the device from the list on the left, your coins are still safe and you can access them by reconnecting your TREZOR again.

+
); } - -export const DisconnectDevice = (props: Props) => { - if (!props.modal.opened) return null; - const { device } = props.modal; - const { onForgetSingleDevice, onCancel } = props.modalActions; - return ( -
-

Unplug { device.instanceLabel }

-

TREZOR Wallet will forget your TREZOR right after you disconnect it.

- TODO: its not true, actually i've already forget those data!!! -
- ); -} \ No newline at end of file diff --git a/src/js/components/modal/index.js b/src/js/components/modal/index.js index 2f4f1053..d75c1559 100644 --- a/src/js/components/modal/index.js +++ b/src/js/components/modal/index.js @@ -19,7 +19,7 @@ import Passphrase from './Passphrase'; import PassphraseType from './PassphraseType'; import ConfirmSignTx from './ConfirmSignTx'; import ConfirmAddress, { ConfirmUnverifiedAddress } from './ConfirmAddress'; -import RememberDevice, { ForgetDevice, DisconnectDevice } from './RememberDevice'; +import RememberDevice, { ForgetDevice } from './RememberDevice'; import DuplicateDevice from './DuplicateDevice'; import * as RECEIVE from '../../actions/constants/receive'; @@ -36,6 +36,7 @@ type StateProps = { accounts: $ElementType, devices: $PropertyType<$ElementType, 'devices'>, connect: $ElementType, + abstractAccount: $ElementType, sendForm: $ElementType, receive: $ElementType, localStorage: $ElementType, @@ -99,10 +100,6 @@ class Modal extends Component { component = () break; - case CONNECT.DISCONNECT_REQUEST : - component = () - break; - case CONNECT.TRY_TO_DUPLICATE : component = () break; @@ -131,6 +128,7 @@ const mapStateToProps: MapStateToProps = (state: St accounts: state.accounts, devices: state.connect.devices, connect: state.connect, + abstractAccount: state.abstractAccount, sendForm: state.sendForm, receive: state.receive, localStorage: state.localStorage diff --git a/src/js/components/wallet/Acquire.js b/src/js/components/wallet/Acquire.js index c5093677..1e35e97b 100644 --- a/src/js/components/wallet/Acquire.js +++ b/src/js/components/wallet/Acquire.js @@ -45,7 +45,7 @@ export default connect( }, (dispatch: Dispatch) => { return { - toggle: bindActionCreators(TrezorConnectActions.acquire, dispatch), + acquireDevice: bindActionCreators(TrezorConnectActions.acquire, dispatch), }; } )(Acquire); diff --git a/src/js/components/wallet/Receive.js b/src/js/components/wallet/Receive.js index 2860e0ec..0b76b09f 100644 --- a/src/js/components/wallet/Receive.js +++ b/src/js/components/wallet/Receive.js @@ -15,13 +15,13 @@ import { default as AbstractAccountActions } from '../../actions/AbstractAccount import type { MapStateToProps, MapDispatchToProps } from 'react-redux'; import type { State, Dispatch } from '../../flowtype'; -import type { StateProps as BaseStateProps, DispatchProps as BaseDispatchProps, Props as BaseProps} from './account/AbstractAccount'; +import type { StateProps as BaseStateProps, DispatchProps as BaseDispatchProps } from './account/AbstractAccount'; import type { AccountState } from './account/AbstractAccount'; type OwnProps = { } -type StateProps = StateProps & { +type StateProps = BaseStateProps & { receive: $ElementType, } @@ -29,7 +29,7 @@ type DispatchProps = BaseDispatchProps & { showAddress: typeof ReceiveActions.showAddress } -type Props = BaseProps & StateProps & DispatchProps; +type Props = StateProps & DispatchProps; class Receive extends AbstractAccount { @@ -43,21 +43,22 @@ const _render = (props: Props, state: AccountState): React$Element => { const { device, account, + discovery, deviceStatusNotification } = state; - if (!device || !account) return
; - const { addressVerified, addressUnverified, } = props.receive; + if (!device || !account || !discovery) return
; + let qrCode = null; let address = `${account.address.substring(0, 20)}...`; let className = 'address hidden'; let button = ( - ); diff --git a/src/js/components/wallet/account/AbstractAccount.js b/src/js/components/wallet/account/AbstractAccount.js index 6ceda855..e18b3d4a 100644 --- a/src/js/components/wallet/account/AbstractAccount.js +++ b/src/js/components/wallet/account/AbstractAccount.js @@ -58,7 +58,9 @@ export default class AbstractAccount

extends Component d.deviceState === device.state && d.network === currentState.network); + if (!discovery) return; const account = props.accounts.find(a => a.deviceState === currentState.deviceState && a.index === currentState.index && a.network === currentState.network); + let deviceStatusNotification: ?React$Element = null; if (account) { @@ -66,6 +68,8 @@ export default class AbstractAccount

extends Component; } else if (!device.available) { deviceStatusNotification = ; + } else if (!discovery.completed) { + deviceStatusNotification = ; } } this.setState({ @@ -108,7 +112,7 @@ export default class AbstractAccount

extends Component - + ); } else { @@ -128,7 +132,7 @@ export default class AbstractAccount

extends Component ); diff --git a/src/js/components/wallet/aside/AccountSelection.js b/src/js/components/wallet/aside/AccountSelection.js index d5d5ff14..cc72a019 100644 --- a/src/js/components/wallet/aside/AccountSelection.js +++ b/src/js/components/wallet/aside/AccountSelection.js @@ -29,8 +29,6 @@ const AccountSelection = (props: Props): ?React$Element => { const fiatRate = props.fiat.find(f => f.network === selectedCoin.network); - // console.warn("AccountSelectionRender", selected, props); - const deviceAddresses: Array = getAccounts(accounts, selected, location.state.network); let selectedAccounts = deviceAddresses.map((address, i) => { // const url: string = `${baseUrl}/network/${location.state.network}/address/${i}`; diff --git a/src/js/components/wallet/aside/CoinSelection.js b/src/js/components/wallet/aside/CoinSelection.js index 52b4bb98..6a0614ff 100644 --- a/src/js/components/wallet/aside/CoinSelection.js +++ b/src/js/components/wallet/aside/CoinSelection.js @@ -11,8 +11,11 @@ const CoinSelection = (props: Props): React$Element => { const { location } = props.router; const { config } = props.localStorage; + const urlParams = location.state; + const baseUrl: string = urlParams.deviceInstance ? `/device/${urlParams.device}:${urlParams.deviceInstance}` : `/device/${urlParams.device}`; + const walletCoins = config.coins.map(item => { - const url = `${ location.pathname }/network/${ item.network }/address/0`; + const url = `${ baseUrl }/network/${ item.network }/address/0`; const className = `coin ${ item.network }` return ( diff --git a/src/js/components/wallet/aside/DeviceSelection.js b/src/js/components/wallet/aside/DeviceSelection.js index 55cff006..866b09cb 100644 --- a/src/js/components/wallet/aside/DeviceSelection.js +++ b/src/js/components/wallet/aside/DeviceSelection.js @@ -104,11 +104,11 @@ const Value = (props: any): any => { export const DeviceSelect = (props: Props) => { const { devices, transport } = props.connect; + const selected: ?TrezorDevice = findSelectedDevice(props.connect); if (!selected) return null; - const handleMenuClick = (type, device) => { - console.log("handleMenuClick", type, device) + const handleMenuClick = (type: string, device: TrezorDevice) => { if (type === 'acquire') { props.acquireDevice(); } else if (type === 'forget') { @@ -118,7 +118,8 @@ export const DeviceSelect = (props: Props) => { } } - const disabled: boolean = (devices.length < 1 && transport && transport.version.indexOf('webusb') < 0); + const webusb: boolean = (transport && transport.version.indexOf('webusb') >= 0) ? true : false; + const disabled: boolean = (devices.length < 1 && !webusb); return ( { } componentDidUpdate() { - const transport: any = this.props.connect.transport; + const { transport } = this.props.connect; if (transport && transport.version.indexOf('webusb') >= 0) TrezorConnect.renderWebUSBButton(); } @@ -163,6 +164,7 @@ export class DeviceDropdown extends Component { block = true; break; } + elem = elem.parentElement; } @@ -178,7 +180,7 @@ export class DeviceDropdown extends Component { componentDidMount(): void { window.addEventListener('mousedown', this.mouseDownHandler, false); // window.addEventListener('blur', this.blurHandler, false); - const transport: any = this.props.connect.transport; + const { transport } = this.props.connect; if (transport && transport.version.indexOf('webusb') >= 0) TrezorConnect.renderWebUSBButton(); } @@ -192,7 +194,6 @@ export class DeviceDropdown extends Component { if (item.type === 'reload') { this.props.acquireDevice(); } else if (item.type === 'forget') { - // this.props.toggleDeviceDropdown(false); this.props.forgetDevice(device); } else if (item.type === 'clone') { this.props.duplicateDevice(device); @@ -244,14 +245,6 @@ export class DeviceDropdown extends Component { ); } - // const currentDeviceMenu = ( - //

- //
Device settings
- //
Clone device
- //
Forget device
- //
- // ); - const deviceList: Array = devices.map((dev, index) => { if (dev === selected) return null; diff --git a/src/js/components/wallet/aside/StickyContainer.js b/src/js/components/wallet/aside/StickyContainer.js index cfd1c14d..2bfac49d 100644 --- a/src/js/components/wallet/aside/StickyContainer.js +++ b/src/js/components/wallet/aside/StickyContainer.js @@ -5,7 +5,6 @@ import React, { PureComponent } from 'react'; import raf from 'raf'; -import { DeviceSelect } from './DeviceSelection'; import { getViewportHeight, getScrollY } from '../../../utils/windowUtils'; type Props = { diff --git a/src/js/components/wallet/send/PendingTransactions.js b/src/js/components/wallet/send/PendingTransactions.js index e9ff9c72..4d9e5bf5 100644 --- a/src/js/components/wallet/send/PendingTransactions.js +++ b/src/js/components/wallet/send/PendingTransactions.js @@ -58,7 +58,7 @@ const PendingTransactions = (props: Props) => {
{ tx.amount } { symbol }
diff --git a/src/js/components/wallet/send/SendForm.js b/src/js/components/wallet/send/SendForm.js index ed0373f6..882762d6 100644 --- a/src/js/components/wallet/send/SendForm.js +++ b/src/js/components/wallet/send/SendForm.js @@ -24,10 +24,11 @@ const _render = (props: Props, state: AccountState): React$Element => { const { device, account, + discovery, deviceStatusNotification } = state; - if (!device || !account) return
; + if (!device || !account || !discovery) return
; const addressTokens = props.tokens.filter(t => t.ethAddress === account.address); const { network } = props.abstractAccount; @@ -95,7 +96,7 @@ const _render = (props: Props, state: AccountState): React$Element => { buttonLabel += ` ${total} ${ selectedCoin.symbol }`; } - if (device) { + //if (device) { if (!device.connected){ buttonLabel = 'Device is not connected'; @@ -103,9 +104,12 @@ const _render = (props: Props, state: AccountState): React$Element => { } else if (!device.available) { buttonLabel = 'Device is unavailable'; buttonDisabled = true; + } else if (!discovery.completed) { + buttonLabel = 'Loading accounts'; + buttonDisabled = true; } - } + //} let notification = null; diff --git a/src/js/components/wallet/summary/Summary.js b/src/js/components/wallet/summary/Summary.js index 052f69c4..dd5ff977 100644 --- a/src/js/components/wallet/summary/Summary.js +++ b/src/js/components/wallet/summary/Summary.js @@ -44,8 +44,11 @@ const _render = (props: Props, state: AccountState): React$Element => { { deviceStatusNotification }

Address #{ parseInt(abstractAccount.index) + 1 }

+ => { onToggle={ props.onDetailsToggle } />

Tokens

- {/* 0x58cda554935e4a1f2acbe15f8757400af275e084 */} + {/* 0x58cda554935e4a1f2acbe15f8757400af275e084 Lahod */} + {/* 0x58cda554935e4a1f2acbe15f8757400af275e084 T01 */}
=> { />
- + diff --git a/src/js/components/wallet/summary/SummaryDetails.js b/src/js/components/wallet/summary/SummaryDetails.js index e6ac888f..ca7ccb8b 100644 --- a/src/js/components/wallet/summary/SummaryDetails.js +++ b/src/js/components/wallet/summary/SummaryDetails.js @@ -7,11 +7,12 @@ import BigNumber from 'bignumber.js'; import type { Props as BaseProps } from './index'; type Props = { + explorer: string, + coin: $PropertyType<$ElementType, 'coin'>, summary: $ElementType, balance: string, network: string, fiat: $ElementType, - localStorage: $ElementType, onToggle: $ElementType } @@ -23,8 +24,7 @@ const SummaryDetails = (props: Props): ?React$Element => { ); - const { config } = props.localStorage; - const selectedCoin = config.coins.find(c => c.network === props.network); + const selectedCoin = props.coin; const fiatRate = props.fiat.find(f => f.network === selectedCoin.network); let balanceColumn = null; @@ -63,6 +63,7 @@ const SummaryDetails = (props: Props): ?React$Element => { return (
+ See full transaction history
{ balanceColumn } { rateColumn } diff --git a/src/js/components/wallet/summary/SummaryTokens.js b/src/js/components/wallet/summary/SummaryTokens.js index f7a594d4..9ea23581 100644 --- a/src/js/components/wallet/summary/SummaryTokens.js +++ b/src/js/components/wallet/summary/SummaryTokens.js @@ -5,11 +5,11 @@ import React from 'react'; import ColorHash from 'color-hash'; import ScaleText from 'react-scale-text'; -import type { Token } from '../../../reducers/TokensReducer'; +import type { Props as BaseProps } from './index'; type Props = { - tokens: Array, - removeToken: (token: Token) => void + tokens: $ElementType, + removeToken: $ElementType } const SummaryTokens = (props: Props) => { diff --git a/src/js/components/wallet/summary/index.js b/src/js/components/wallet/summary/index.js index f3510c30..0e300674 100644 --- a/src/js/components/wallet/summary/index.js +++ b/src/js/components/wallet/summary/index.js @@ -13,11 +13,11 @@ import * as TokenActions from '../../../actions/TokenActions'; import type { ActionCreators } from 'redux'; import type { MapStateToProps, MapDispatchToProps } from 'react-redux'; import type { State, Dispatch } from '../../../flowtype'; -import type { StateProps as BaseStateProps, DispatchProps as BaseDispatchProps, Props as BaseProps} from '../account/AbstractAccount'; +import type { StateProps as BaseStateProps, DispatchProps as BaseDispatchProps } from '../account/AbstractAccount'; type OwnProps = { } -type StateProps = StateProps & { +type StateProps = BaseStateProps & { tokens: $ElementType, summary: $ElementType, fiat: $ElementType, @@ -34,7 +34,7 @@ type DispatchProps = BaseDispatchProps & { removeToken: typeof TokenActions.remove, } -export type Props = BaseProps & StateProps & DispatchProps; +export type Props = StateProps & DispatchProps; const mapStateToProps: MapStateToProps = (state: State, own: OwnProps): StateProps => { return { diff --git a/src/js/flowtype/bignumber.js b/src/js/flowtype/bignumber.js new file mode 100644 index 00000000..0853e3c6 --- /dev/null +++ b/src/js/flowtype/bignumber.js @@ -0,0 +1,55 @@ +declare module 'bignumber.js' { + declare type $npm$big$number$object = number | string | BigNumber + declare type $npm$cmp$result = -1 | 0 | 1 + declare type DIGIT = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 + declare type ROUND_DOWN = 0 + declare type ROUND_HALF_UP = 1 + declare type ROUND_HALF_EVEN = 2 + declare type ROUND_UP = 3 + declare type RM = ROUND_DOWN | ROUND_HALF_UP | ROUND_HALF_EVEN | ROUND_UP + + declare class BigNumber { + // Properties + static DP: number; + static RM: RM; + static E_NEG: number; + static E_POS: number; + + c: Array; + e: number; + s: -1 | 1; + + // Constructors + static (value: $npm$big$number$object): BigNumber; + constructor(value: $npm$big$number$object): BigNumber; + + // Methods + abs(): BigNumber; + cmp(n: $npm$big$number$object): $npm$cmp$result; + div(n: $npm$big$number$object): BigNumber; + dividedBy(n: $npm$big$number$object): BigNumber; + eq(n: $npm$big$number$object): boolean; + gt(n: $npm$big$number$object): boolean; + greaterThan(n: $npm$big$number$object): boolean; + gte(n: $npm$big$number$object): boolean; + lt(n: $npm$big$number$object): boolean; + lessThan(n: $npm$big$number$object): boolean; + lte(n: $npm$big$number$object): boolean; + lessThanOrEqualTo(n: $npm$big$number$object): boolean; + minus(n: $npm$big$number$object): BigNumber; + mod(n: $npm$big$number$object): BigNumber; + plus(n: $npm$big$number$object): BigNumber; + pow(exp: number): BigNumber; + round(dp: ?number, rm: ?RM): BigNumber; + sqrt(): BigNumber; + times(n: $npm$big$number$object): BigNumber; + toExponential(dp: ?number): string; + toFixed(dp: ?number): string; + toPrecision(sd: ?number): string; + toString(): string; + valueOf(): string; + toJSON(): string; + } + + declare module.exports: typeof BigNumber +} \ No newline at end of file diff --git a/src/js/flowtype/ethereum-types.js b/src/js/flowtype/ethereum-types.js new file mode 100644 index 00000000..fa0a0aeb --- /dev/null +++ b/src/js/flowtype/ethereum-types.js @@ -0,0 +1,72 @@ +declare module 'ethereum-types' { + // start data types + declare export type EthereumUnitT = + | 'kwei' + | 'ada' + | 'mwei' + | 'babbage' + | 'gwei' + | 'shannon' + | 'szabo' + | 'finney' + | 'ether' + | 'kether' + | 'grand' + | 'einstein' + | 'mether' + | 'gether' + | 'tether' + + declare export type EthereumAddressT = string + declare export type EthereumBlockNumberT = number + declare export type EthereumBlockHashT = string + declare export type EthereumTransactionHashT = string + // end data types + + // start contract types + declare export type EthereumWatchErrorT = ?Object + + declare export type EthereumEventT = { + address: EthereumAddressT, + args: A, + blockHash: EthereumBlockHashT, + blockNumber: number, + event: string, + logIndex: number, + transactionHash: EthereumTransactionHashT, + transactionIndex: number, + transactionLogIndex: string, + type: 'mined' // TODO: what other types are there? + } + + // this represents the setup object returned from truffle-contract + // we use it to get a known contact `at(address)` (ie. for POATokenContract addresses) + declare export type EthereumContractSetupT = { + at: EthereumAddressT => Promise + } + + declare export type EthereumSendTransactionOptionsT = { + from: EthereumAddressT, + gas: number, + value?: number + } + + declare export type EthereumSendTransactionT = EthereumSendTransactionOptionsT => Promise< + EthereumTransactionHashT + > + + // TODO(mattgstevens): it would be nice to have an Generic type for a Contract instance + // similar to the EthererumWatchEventT + // + // declare export type SendTransactionContractT = interface .sendTransaction(EthereumAddressT) + // declare export type WatchableContractT = (error: Object, response: A) + + // declare export type EthereumContractWatcherT = (options: { + // fromBlock?: EthereumBlockNumberT, + // toBlock?: EthereumBlockNumberT, + // address?: EthereumAddressT + // }) => * + + // end contract data +} + \ No newline at end of file diff --git a/src/js/flowtype/trezor-connect.js b/src/js/flowtype/trezor-connect.js index 7d49d833..4d647cef 100644 --- a/src/js/flowtype/trezor-connect.js +++ b/src/js/flowtype/trezor-connect.js @@ -92,7 +92,11 @@ declare module 'trezor-connect' { declare export type UiMessage = { event: string; type: UiMessageType; - payload: Object; + // payload: Object; + payload: { + device: Device; + code?: string; + } } declare export type DeviceMessageType = $Values; diff --git a/src/js/flowtype/web3.js b/src/js/flowtype/web3.js index 4343fbbe..9c31ad1c 100644 --- a/src/js/flowtype/web3.js +++ b/src/js/flowtype/web3.js @@ -1,4 +1,81 @@ +import type BigNumber from 'bignumber.js'; +import type { EthereumUnitT, EthereumAddressT } from 'ethereum-types'; + declare module 'web3' { + declare type ProviderT = Object; + + declare class Web3T { + static providers: { + HttpProvider: (url: string) => ProviderT; + }; + + constructor(ProviderT): Web3T; + currentProvider: ProviderT; + eth: Eth; + + toHex: (str: string | number) => string; + isAddress: (address: string) => boolean; + toWei: (number: BigNumber, unit?: EthereumUnitT) => BigNumber; + toWei: (number: string, unit?: EthereumUnitT) => string; + toDecimal: (number: BigNumber) => number; + toDecimal: (number: string) => number; + soliditySha3: (payload: string | number | BigNumber | Object) => String; + + fromWei: (number: string, unit?: EthereumUnitT) => string; + version: { + api: string; + network: string; + // and many more + } + + } + + declare class Eth { + getGasPrice: (callback: (error: Error, gasPrice: string) => void) => void, + getBalance: (address: string, callback: (error: Error, balance: BigNumber) => void) => void, + getTransactionCount: (address: string, callback: (error: Error, result: number) => void) => void, + getTransaction: (txid: string, callback: (error: Error, result: any) => void) => void, + getBlockNumber: (callback: (error: Error, blockNumber: number) => void) => void, + getBlock: (hash: string, callback: (error: Error, result: any) => void) => void, + getAccounts: (callback: (error: Error, accounts: Array) => void) => void, + sign: (payload: string, signer: EthereumAddressT) => Promise, + contract: (abi: Array) => ContractFactory, + estimateGas: (options: any, callback: (error: Error, result: any) => void) => void, + sendRawTransaction: (tx: any, callback: (error: Error, result: any) => void) => void, + filter: (type: string) => Filter; // return intance with "watch" + } + + declare export class Filter { + watch: (callback: (error: ?Error, blockHash: ?string) => void | Promise) => void, + stopWatching: (callback: any) => void, + } + + declare export class ContractFactory { + // constructor(abi: Array); + eth: Eth; + abi: Array; + at: (address: string, callback: (error: Error, contract: Contract) => void) => Contract; + } + + declare export class Contract { + name: (callback: (error: Error, name: string) => void) => void; + symbol: (callback: (error: Error, symbol: string) => void) => void; + decimals: (callback: (error: Error, decimals: BigNumber) => void) => void; + balanceOf: (address: string, callback: (error: Error, balance: BigNumber) => void) => void; + transfer: any; + } + + declare export default typeof Web3T; +} + + + +// +// + + + +/*declare module 'web3' { module.exports = { eth: { @@ -72,4 +149,5 @@ declare module 'web3' { }; } } -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/src/js/reducers/AbstractAccountReducer.js b/src/js/reducers/AbstractAccountReducer.js index da8b6152..e5c83454 100644 --- a/src/js/reducers/AbstractAccountReducer.js +++ b/src/js/reducers/AbstractAccountReducer.js @@ -31,7 +31,10 @@ export const initialState: State = { defaultGasLimit: 0, defaultGasLimitTokens: 0, defaultGasPrice: 0, - explorer: '', + explorer: { + tx: '', + address: '' + }, tokens: '', backends: [] }, diff --git a/src/js/reducers/LocalStorageReducer.js b/src/js/reducers/LocalStorageReducer.js index 85c48d14..761a1a14 100644 --- a/src/js/reducers/LocalStorageReducer.js +++ b/src/js/reducers/LocalStorageReducer.js @@ -13,9 +13,15 @@ export type Coin = { defaultGasLimit: number; defaultGasLimitTokens: number; defaultGasPrice: number; - explorer: string; + explorer: { + tx: string; + address: string; + }; tokens: string; - backends: Array + backends: Array<{ + name: string; + urls: Array; + }> } export type NetworkToken = { diff --git a/src/js/reducers/LogReducer.js b/src/js/reducers/LogReducer.js index 14eeb594..2655579d 100644 --- a/src/js/reducers/LogReducer.js +++ b/src/js/reducers/LogReducer.js @@ -4,10 +4,11 @@ import * as LOG from '../actions/constants/log'; import type { Action } from '../flowtype'; -type LogEntry = { +export type LogEntry = { time: number; type: string; - messgage: string; + // message: string; + message: any; } export type State = { @@ -25,22 +26,23 @@ export default (state: State = initialState, action: Action): State => { switch (action.type) { - case LOG.OPEN: + case LOG.OPEN : return { ...state, opened: true } - case LOG.CLOSE: + case LOG.CLOSE : return { ...state, opened: false } - // case 'log__add': - // return { - // ...state, - // } + case LOG.ADD : + return { + ...state, + entries: state.entries.concat([ action.payload ]) + } default: return state; diff --git a/src/js/reducers/ModalReducer.js b/src/js/reducers/ModalReducer.js index e1e9f812..077acaf3 100644 --- a/src/js/reducers/ModalReducer.js +++ b/src/js/reducers/ModalReducer.js @@ -42,7 +42,6 @@ export default function modal(state: State = initialState, action: Action): Stat windowType: action.type }; case CONNECT.FORGET_REQUEST : - case CONNECT.DISCONNECT_REQUEST : return { opened: true, device: action.device, @@ -88,7 +87,6 @@ export default function modal(state: State = initialState, action: Action): Stat }; case UI.REQUEST_BUTTON : - console.log("REQBUT", action) return { opened: true, device: action.payload.device, diff --git a/src/js/reducers/TrezorConnectReducer.js b/src/js/reducers/TrezorConnectReducer.js index 2350e358..23d1878c 100644 --- a/src/js/reducers/TrezorConnectReducer.js +++ b/src/js/reducers/TrezorConnectReducer.js @@ -17,7 +17,17 @@ export type State = { selectedDevice: ?SelectedDevice; discoveryComplete: boolean; error: ?string; - transport: any; + transport: ?{ + type: string; + version: string; + }; + // browserState: { + // name: string; + // osname: string; + // supported: boolean; + // outdated: boolean; + // mobile: boolean; + // } | {}; browserState: any; } @@ -68,7 +78,6 @@ const mergeDevices = (current: TrezorDevice, upcoming: Object): TrezorDevice => // if (upcoming.features.passphrase_protection !== current.features.passphrase_protection) { // // device settings has been changed, reset state // // dev.state = null; - // // console.log("RESTETTTT STATE!"); // } // } @@ -199,7 +208,6 @@ const setDeviceState = (state: State, action: any): State => { //const affectedDevice: ?TrezorDevice = state.devices.find(d => d.path === action.device.path && d.instance === action.device.instance); const index: number = state.devices.findIndex(d => d.path === action.device.path && d.instance === action.device.instance); if (index > -1) { - console.warn("APGREDJS", newState.devices[index].state) // device could already have own state from firmware, do not override it if (!newState.devices[index].state) { const changedDevice: TrezorDevice = { @@ -239,15 +247,10 @@ const changeDevice = (state: State, device: Object): State => { // else if (isAffectedUnacquired >= 0 && !device.unacquired && affectedDevices.length > 1) { // affectedDevices.splice(isAffectedUnacquired, 1); - // console.warn("CLEARRRR", isAffectedUnacquired); // } - console.warn("AFFEEE", isAffectedUnacquired, affectedDevices, otherDevices) - - // acquiring selected device. remove unnecessary (not acquired) device from list // after this action selectedDevice needs to be updated (in TrezorConnectService) if (state.selectedDevice && device.path === state.selectedDevice.id && affectedDevices.length > 1) { - console.warn("clear dupli", affectedDevices, otherDevices) // affectedDevices = affectedDevices.filter(d => d.path !== state.selectedDevice.id && d.features); } @@ -358,7 +361,6 @@ const onSelectDevice = (state: State, action: any): State => { const selected = findSelectedDevice(newState); if (selected) { selected.ts = new Date().getTime(); - console.warn("APDEJT SELECTED!", selected.instanceLabel, selected.ts) } return newState; @@ -435,13 +437,7 @@ export default function connect(state: State = initialState, action: Action): St case DEVICE.DISCONNECT_UNACQUIRED : return disconnectDevice(state, action.device); - - - - - - default: return state; diff --git a/src/js/reducers/WalletReducer.js b/src/js/reducers/WalletReducer.js index 1cf8278c..43b38354 100644 --- a/src/js/reducers/WalletReducer.js +++ b/src/js/reducers/WalletReducer.js @@ -1,17 +1,22 @@ /* @flow */ 'use strict'; +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 type { Action, RouterLocationState } from '../flowtype'; + +import type { Action, RouterLocationState, TrezorDevice } from '../flowtype'; type State = { ready: boolean; dropdownOpened: boolean; initialParams: ?RouterLocationState; initialPathname: ?string; + disconnectRequest: ?TrezorDevice; } const initialState: State = { @@ -19,6 +24,7 @@ const initialState: State = { dropdownOpened: false, initialParams: null, initialPathname: null, + disconnectRequest: null }; export default function wallet(state: State = initialState, action: Action): State { @@ -43,12 +49,28 @@ export default function wallet(state: State = initialState, action: Action): Sta dropdownOpened: action.opened } + case LOCATION_CHANGE : case MODAL.CLOSE : return { ...state, dropdownOpened: false } + case CONNECT.DISCONNECT_REQUEST : + return { + ...state, + disconnectRequest: action.device + } + + case DEVICE.DISCONNECT : + if (state.disconnectRequest && action.device.path === state.disconnectRequest.path) { + return { + ...state, + disconnectRequest: null + } + } + return state; + default: return state; } diff --git a/src/js/services/LogService.js b/src/js/services/LogService.js new file mode 100644 index 00000000..cc8ebf5a --- /dev/null +++ b/src/js/services/LogService.js @@ -0,0 +1,40 @@ +/* @flow */ +'use strict'; + +import * as LogActions from '../actions/LogActions'; +import * as STORAGE from '../actions/constants/localStorage'; +import { OPEN, CLOSE, ADD } from '../actions/constants/log'; + +import type { + Middleware, + MiddlewareAPI, + MiddlewareDispatch, + State, + Dispatch, + Action, + AsyncAction, + GetState +} from '../flowtype'; + +const exclude: Array = [ + ADD, OPEN, CLOSE, + STORAGE.READY, + "web3__create" +]; + +/** + * Middleware + */ +const LogService: Middleware = (api: MiddlewareAPI) => (next: MiddlewareDispatch) => (action: Action): Action => { + + next(action); + + if (exclude.indexOf(action.type) < 0) { + // api.dispatch(LogActions.add(action.type, JSON.stringify( action ))); + api.dispatch(LogActions.add(action.type, action)); + } + + return action; +}; + +export default LogService; \ No newline at end of file diff --git a/src/js/services/TrezorConnectService.js b/src/js/services/TrezorConnectService.js index 65f3ea84..09dcad4c 100644 --- a/src/js/services/TrezorConnectService.js +++ b/src/js/services/TrezorConnectService.js @@ -65,15 +65,13 @@ const TrezorConnectService: Middleware = (api: MiddlewareAPI) => (next: Middlewa //api.dispatch( TrezorConnectActions.forgetDevice(action.device) ); api.dispatch( TrezorConnectActions.switchToFirstAvailableDevice() ); } else if (action.type === CONNECT.FORGET_SINGLE) { - - //api.dispatch( TrezorConnectActions.forgetDevice(action.device) ); - if (api.getState().connect.devices.length < 1 && action.device.connected) { - // prompt disconnect device modal + // prompt disconnect device info in LandingPage api.dispatch({ type: CONNECT.DISCONNECT_REQUEST, device: action.device }); + api.dispatch( push('/') ); } else { api.dispatch( TrezorConnectActions.switchToFirstAvailableDevice() ); } @@ -82,7 +80,6 @@ const TrezorConnectService: Middleware = (api: MiddlewareAPI) => (next: Middlewa // we need to change route if (prevState.selectedDevice) { if (!action.device.unacquired && action.device.path === prevState.selectedDevice.id) { - console.warn("TODO: here! better") api.dispatch( TrezorConnectActions.onSelectDevice(action.device) ); } } diff --git a/src/js/services/index.js b/src/js/services/index.js index 1aa2b6b9..21917ca4 100644 --- a/src/js/services/index.js +++ b/src/js/services/index.js @@ -1,12 +1,14 @@ /* @flow */ 'use strict'; +import LogService from './LogService'; import RouterService from './RouterService'; import LocalStorageService from './LocalStorageService'; import CoinmarketcapService from './CoinmarketcapService'; import TrezorConnectService from './TrezorConnectService'; export default [ + LogService, RouterService, LocalStorageService, TrezorConnectService, diff --git a/src/js/store/index.js b/src/js/store/index.js index 98a747c9..35740084 100644 --- a/src/js/store/index.js +++ b/src/js/store/index.js @@ -12,9 +12,9 @@ import reducers from '../reducers'; import services from '../services'; import RavenMiddleware from 'redux-raven-middleware'; -import type { Store } from '../flowtype'; +import type { Action, GetState, Store } from '../flowtype'; -export const history = createHistory( { queryKey: false } ); +export const history: History = createHistory( { queryKey: false } ); const initialState: any = {}; const enhancers = []; @@ -24,33 +24,40 @@ const middleware = [ routerMiddleware(history) ]; -const excludeLogger = (getState: any, action: any): boolean => { - //'@@router/LOCATION_CHANGE' - const excluded: Array = ['LOG_TO_EXCLUDE']; - const pass: Array = excluded.filter((act) => { - return action.type === act; - }); - return pass.length === 0; -} - -const logger = createLogger({ - level: 'info', - // predicate: excludeLogger, - collapsed: true -}); +let composedEnhancers: any; if (process.env.NODE_ENV === 'development') { + + const excludeLogger = (getState: GetState, action: Action): boolean => { + //'@@router/LOCATION_CHANGE' + const excluded: Array = ['LOG_TO_EXCLUDE', 'log__add']; + const pass: Array = excluded.filter((act) => { + return action.type === act; + }); + return pass.length === 0; + } + + const logger = createLogger({ + level: 'info', + predicate: excludeLogger, + collapsed: true + }); + const devToolsExtension: ?Function = window.devToolsExtension; if (typeof devToolsExtension === 'function') { enhancers.push(devToolsExtension()); } -} -const composedEnhancers = compose( - // applyMiddleware(...middleware, logger, ...services), - applyMiddleware(...middleware, logger, ...services), - ...enhancers -); + composedEnhancers = compose( + applyMiddleware(...middleware, logger, ...services), + ...enhancers + ); +} else { + composedEnhancers = compose( + applyMiddleware(...middleware, ...services), + ...enhancers + ); +} export default createStore( reducers, diff --git a/src/styles/log.less b/src/styles/log.less index 1b69b590..dc578b75 100644 --- a/src/styles/log.less +++ b/src/styles/log.less @@ -43,6 +43,7 @@ height: 200px; min-height: 200px; resize: vertical; + font-size: 10px; &:focus { box-shadow: none; } diff --git a/src/styles/summary.less b/src/styles/summary.less index 26ac2664..137e6c34 100644 --- a/src/styles/summary.less +++ b/src/styles/summary.less @@ -61,6 +61,7 @@ .content { display: flex; padding-bottom: 32px; + padding-top: 24px; .column { margin-right: 48px; @@ -73,7 +74,7 @@ .fiat-value { font-weight: 500; font-size: 18px; - margin: 7px 0 6px 0; + margin: 7px 0px 7px 0px; color: @color_text_primary; } }