before testing

pull/2/merge
Szymon Lesisz 6 years ago
parent 0bc4dd3cf9
commit 1c89f3e975

@ -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]

@ -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/"
}
}
],

@ -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
}
}
}

@ -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<number>): AsyncAction => {
return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
const selected = findSelectedDevice(getState().connect);

@ -118,10 +118,10 @@ const getMaxAmount = () => {
}
export const getFeeLevels = (symbol: string, gasPrice: BigNumber | string, gasLimit: string): Array<FeeLevel> => {
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: `<a href="${ selectedCoin.explorer }/tx/${txid}" class="green" target="_blank" rel="noreferrer noopener">See transaction detail</a>`,
message: `<a href="${selectedCoin.explorer.tx}${txid}" class="green" target="_blank" rel="noreferrer noopener">See transaction detail</a>`,
cancelable: true,
actions: []
}

@ -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<void> => {
const selected = findSelectedDevice(getState().connect);
console.warn("init selected", selected)
if (selected
&& selected.connected
&& selected.features

@ -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<any> => {
});
}
export const getTokenBalanceAsync = (erc20: any, token: string, address: string): Promise<any> => {
export const getTokenBalanceAsync = (erc20: any, token: string, address: string): Promise<string> => {
return new Promise((resolve, reject) => {
const contr = erc20.at(token);
@ -383,26 +379,27 @@ export const getNonceAsync = (web3: Web3, address: string): Promise<number> => {
export const getTokenInfoAsync = (erc20: any, address: string): Promise<any> => {
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;
}

@ -2,4 +2,5 @@
'use strict';
export const OPEN: 'log__open' = 'log__open';
export const CLOSE: 'log__close' = 'log__close';
export const CLOSE: 'log__close' = 'log__close';
export const ADD: 'log__add' = 'log__add';

@ -16,13 +16,19 @@ type Props = {
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 }></button>
<h2>Log</h2>
<p>Attention: The log contains your XPUBs. Anyone with your XPUBs can see your account history.</p>
<textarea></textarea>
<textarea value={ JSON.stringify(props.log.entries) } readOnly></textarea>
</div>
)
}

@ -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<State, 'connect'>, 'transport'>;
disconnectRequest: ?TrezorDevice;
}
export default class InstallBridge extends Component<Props> {
const DisconnectDevice = (props: Props) => {
if (!props.disconnectRequest) return null;
return (
<main>
<h2 className="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 { props.disconnectRequest.instanceLabel } device.
</span>
</p>
</div>
<div className="image">
</div>
</main>
)
}
const ConnectHIDDevice = (props: Props) => {
return (
<main>
<h2 className="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>
<rect className="connect-usb-cable" stroke="#01B757" strokeWidth="1" x="8.5" y="44.5" width="1" height="11"></rect>
<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"></path>
<rect fill="#01B757" x="2" y="7" width="14" height="7" rx="0.5625"></rect>
</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>
);
}
class ConnectWebUsbDevice extends Component<Props> {
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 = <button className="trezor-webusb-button">Check for devices</button>;
connectClaim = 'Connect TREZOR';
and = <p>and</p>;
bridgeClaim = <span>Device not recognized? <a href="#/bridge" className="green">Try installing the TREZOR Bridge.</a></span>;
}
return (
<main>
<h2 className="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={ css }>
<div className="row webusb">
<p className="connect">
<span>
<svg width="12px" height="35px" viewBox="0 0 20 57">
@ -53,7 +87,7 @@ export default class InstallBridge extends Component<Props> {
<rect fill="#01B757" x="2" y="7" width="14" height="7" rx="0.5625"></rect>
</g>
</svg>
{ connectClaim }
Connect TREZOR
</span>
</p>
<p className="webusb-and">and</p>
@ -61,11 +95,24 @@ export default class InstallBridge extends Component<Props> {
</div>
<div className="image">
<p>
{ bridgeClaim }
<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>
);
}
}
}
const ConnectDevice = (props: Props) => {
const { transport, disconnectRequest } = props;
if (disconnectRequest) {
return <DisconnectDevice {...props} />
} else if (transport && transport.version.indexOf('webusb') >= 0) {
return <ConnectWebUsbDevice {...props} />
} else {
return <ConnectHIDDevice {...props} />
}
}
export default ConnectDevice;

@ -43,7 +43,7 @@ export default class InstallBridge extends Component<Props, State> {
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<Props, State> {
});
}
componentWillUpdate() {
if (this.props.browserState.osname && !this.state.target) {
const currentTarget: ?InstallTarget = installers.find(i => i.id === this.props.browserState.osname);

@ -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 = <InstallBridge browserState={ browserState } />;
} else if (props.wallet.ready && devices.length < 1) {
css += ' connect-device';
body = <ConnectDevice transport={ transport } />;
body = <ConnectDevice transport={ transport } disconnectRequest={ props.wallet.disconnectRequest } />;
}
if (notification || body) {

@ -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 (
<div className="confirm-address">
@ -18,16 +21,21 @@ const ConfirmAddress = (props: any): any => {
</div>
<div className="content">
<p>{ account.address }</p>
<label>{ selectedCoin.symbol } account #{ (account.index + 1) }</label>
<label>{ abstractAccount.coin.symbol } account #{ (account.index + 1) }</label>
</div>
</div>
);
}
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 (
<div className="confirm-address-unverified">
@ -59,7 +66,8 @@ export const ConfirmUnverifiedAddress = (props: any): any => {
</div>
);
} 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 (
<div className="confirm-address-unverified">
<button className="close-modal transparent" onClick={ onCancel }></button>

@ -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 (

@ -67,17 +67,21 @@ export default class RememberDevice extends Component<Props, State> {
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 (<span key={index}>{instance.instanceLabel}</span>);
let comma: string = '';
if (index > 0) comma = ', ';
return (
<span key={ index }>{ comma }{ instance.instanceLabel }</span>
);
})
devicePlural = instances.length > 1;
devicePlural = "devices or to remember them";
}
return (
<div className="remember">
<h3>Forget {label}?</h3>
<p>Would you like TREZOR Wallet to forget your device or to remember it, so that it is still visible even while disconnected?</p>
<p>Would you like TREZOR Wallet to forget your { devicePlural }, so that it is still visible even while disconnected?</p>
<button onClick={ event => onForgetDevice(device) }>Forget</button>
<button className="white" onClick={ event => onRememberDevice(device) }><span>Remember <Loader size="28" label={ this.state.countdown.toString() } /></span></button>
</div>
@ -92,22 +96,9 @@ export const ForgetDevice = (props: Props) => {
return (
<div className="remember">
<h3>Forget { device.instanceLabel } ?</h3>
<p>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.</p>
<button onClick={ event => onForgetSingleDevice(device) }>Forget</button>
<p>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.</p>
<button onClick={ (event) => onForgetSingleDevice(device) }>Forget</button>
<button className="white" onClick={ onCancel }>Don't forget</button>
</div>
);
}
export const DisconnectDevice = (props: Props) => {
if (!props.modal.opened) return null;
const { device } = props.modal;
const { onForgetSingleDevice, onCancel } = props.modalActions;
return (
<div className="remember">
<h3>Unplug { device.instanceLabel }</h3>
<p>TREZOR Wallet will forget your TREZOR right after you disconnect it.</p>
<b>TODO: its not true, actually i've already forget those data!!!</b>
</div>
);
}

@ -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<State, 'accounts'>,
devices: $PropertyType<$ElementType<State, 'connect'>, 'devices'>,
connect: $ElementType<State, 'connect'>,
abstractAccount: $ElementType<State, 'abstractAccount'>,
sendForm: $ElementType<State, 'sendForm'>,
receive: $ElementType<State, 'receive'>,
localStorage: $ElementType<State, 'localStorage'>,
@ -99,10 +100,6 @@ class Modal extends Component<Props> {
component = (<ForgetDevice { ...this.props } />)
break;
case CONNECT.DISCONNECT_REQUEST :
component = (<DisconnectDevice { ...this.props } />)
break;
case CONNECT.TRY_TO_DUPLICATE :
component = (<DuplicateDevice { ...this.props } />)
break;
@ -131,6 +128,7 @@ const mapStateToProps: MapStateToProps<State, OwnProps, StateProps> = (state: St
accounts: state.accounts,
devices: state.connect.devices,
connect: state.connect,
abstractAccount: state.abstractAccount,
sendForm: state.sendForm,
receive: state.receive,
localStorage: state.localStorage

@ -45,7 +45,7 @@ export default connect(
},
(dispatch: Dispatch) => {
return {
toggle: bindActionCreators(TrezorConnectActions.acquire, dispatch),
acquireDevice: bindActionCreators(TrezorConnectActions.acquire, dispatch),
};
}
)(Acquire);

@ -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<State, 'receive'>,
}
@ -29,7 +29,7 @@ type DispatchProps = BaseDispatchProps & {
showAddress: typeof ReceiveActions.showAddress
}
type Props = BaseProps & StateProps & DispatchProps;
type Props = StateProps & DispatchProps;
class Receive extends AbstractAccount<Props> {
@ -43,21 +43,22 @@ const _render = (props: Props, state: AccountState): React$Element<string> => {
const {
device,
account,
discovery,
deviceStatusNotification
} = state;
if (!device || !account) return <section></section>;
const {
addressVerified,
addressUnverified,
} = props.receive;
if (!device || !account || !discovery) return <section></section>;
let qrCode = null;
let address = `${account.address.substring(0, 20)}...`;
let className = 'address hidden';
let button = (
<button onClick={ event => props.showAddress(account.addressPath) }>
<button disabled={ !discovery.completed } onClick={ event => props.showAddress(account.addressPath) }>
<span>Show full address</span>
</button>
);

@ -58,7 +58,9 @@ export default class AbstractAccount<P> extends Component<Props & P, AccountStat
const device = findDevice(props.devices, currentState.deviceState, currentState.deviceId, currentState.deviceInstance);
if (!device) return;
const discovery = props.discovery.find(d => 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<typeof Notification> = null;
if (account) {
@ -66,6 +68,8 @@ export default class AbstractAccount<P> extends Component<Props & P, AccountStat
deviceStatusNotification = <Notification className="info" title={ `Device ${ device.instanceLabel } is disconnected` } />;
} else if (!device.available) {
deviceStatusNotification = <Notification className="info" title={ `Device ${ device.instanceLabel } is unavailable` } message="Change passphrase settings to use this device" />;
} else if (!discovery.completed) {
deviceStatusNotification = <Notification className="info" title="Loading accounts" />;
}
}
this.setState({
@ -108,7 +112,7 @@ export default class AbstractAccount<P> extends Component<Props & P, AccountStat
if (device.available) {
return (
<section>
<Notification className="info" title="Loading account" />
<Notification className="info" title="Loading accounts" />
</section>
);
} else {
@ -128,7 +132,7 @@ export default class AbstractAccount<P> extends Component<Props & P, AccountStat
<Notification
className="info"
title={ `Device ${ device.instanceLabel } is disconnected` }
message="Connect to load accounts"
message="Connect device to load accounts"
/>
</section>
);

@ -29,8 +29,6 @@ const AccountSelection = (props: Props): ?React$Element<string> => {
const fiatRate = props.fiat.find(f => f.network === selectedCoin.network);
// console.warn("AccountSelectionRender", selected, props);
const deviceAddresses: Array<any> = getAccounts(accounts, selected, location.state.network);
let selectedAccounts = deviceAddresses.map((address, i) => {
// const url: string = `${baseUrl}/network/${location.state.network}/address/${i}`;

@ -11,8 +11,11 @@ const CoinSelection = (props: Props): React$Element<string> => {
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 (
<NavLink key={ item.network } to={ url } className={ className }>

@ -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 (
<Value
@ -150,7 +151,7 @@ export class DeviceDropdown extends Component<Props> {
}
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<Props> {
block = true;
break;
}
elem = elem.parentElement;
}
@ -178,7 +180,7 @@ export class DeviceDropdown extends Component<Props> {
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<Props> {
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<Props> {
);
}
// const currentDeviceMenu = (
// <div className="device-menu">
// <div className="settings">Device settings</div>
// <div className="clone">Clone device</div>
// <div className="forget">Forget device</div>
// </div>
// );
const deviceList: Array<any> = devices.map((dev, index) => {
if (dev === selected) return null;

@ -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 = {

@ -58,7 +58,7 @@ const PendingTransactions = (props: Props) => {
</div>
</div>
<div className="name">
<a href={ `${props.selectedCoin.explorer}/tx/${tx.id}`} target="_blank" rel="noreferrer noopener">{ name }</a>
<a href={ `${props.selectedCoin.explorer.tx}${tx.id}`} target="_blank" rel="noreferrer noopener">{ name }</a>
</div>
<div className="amount">{ tx.amount } { symbol }</div>
</div>

@ -24,10 +24,11 @@ const _render = (props: Props, state: AccountState): React$Element<string> => {
const {
device,
account,
discovery,
deviceStatusNotification
} = state;
if (!device || !account) return <section></section>;
if (!device || !account || !discovery) return <section></section>;
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<string> => {
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<string> => {
} else if (!device.available) {
buttonLabel = 'Device is unavailable';
buttonDisabled = true;
} else if (!discovery.completed) {
buttonLabel = 'Loading accounts';
buttonDisabled = true;
}
}
//}
let notification = null;

@ -44,8 +44,11 @@ const _render = (props: Props, state: AccountState): React$Element<string> => {
{ deviceStatusNotification }
<h2 className={ `summary-header ${abstractAccount.network}` }>Address #{ parseInt(abstractAccount.index) + 1 }</h2>
<SummaryDetails
explorer={ `${abstractAccount.coin.explorer.address}${account.address}` }
coin={ abstractAccount.coin }
summary={ props.summary }
balance={ account.balance }
network={ abstractAccount.network }
@ -54,7 +57,8 @@ const _render = (props: Props, state: AccountState): React$Element<string> => {
onToggle={ props.onDetailsToggle } />
<h2>Tokens</h2>
{/* 0x58cda554935e4a1f2acbe15f8757400af275e084 */}
{/* 0x58cda554935e4a1f2acbe15f8757400af275e084 Lahod */}
{/* 0x58cda554935e4a1f2acbe15f8757400af275e084 T01 */}
<div className="filter">
<Async
className="token-select"
@ -81,7 +85,7 @@ const _render = (props: Props, state: AccountState): React$Element<string> => {
/>
</div>
<SummaryTokens tokens={ tokens } removeToken={ props.removeToken } />
</section>

@ -7,11 +7,12 @@ import BigNumber from 'bignumber.js';
import type { Props as BaseProps } from './index';
type Props = {
explorer: string,
coin: $PropertyType<$ElementType<BaseProps, 'abstractAccount'>, 'coin'>,
summary: $ElementType<BaseProps, 'summary'>,
balance: string,
network: string,
fiat: $ElementType<BaseProps, 'fiat'>,
localStorage: $ElementType<BaseProps, 'localStorage'>,
onToggle: $ElementType<BaseProps, 'onDetailsToggle'>
}
@ -23,8 +24,7 @@ const SummaryDetails = (props: Props): ?React$Element<string> => {
</div>
);
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<string> => {
return (
<div className="summary-details opened">
<div className="toggle" onClick={ props.onToggle }></div>
<a href={ props.explorer } className="green" target="_blank" rel="noreferrer noopener">See full transaction history</a>
<div className="content">
{ balanceColumn }
{ rateColumn }

@ -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<Token>,
removeToken: (token: Token) => void
tokens: $ElementType<BaseProps, 'tokens'>,
removeToken: $ElementType<BaseProps, 'removeToken'>
}
const SummaryTokens = (props: Props) => {

@ -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<State, 'tokens'>,
summary: $ElementType<State, 'summary'>,
fiat: $ElementType<State, 'fiat'>,
@ -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, OwnProps, StateProps> = (state: State, own: OwnProps): StateProps => {
return {

@ -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<DIGIT>;
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
}

@ -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<A> = {
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<A> = {
at: EthereumAddressT => Promise<A>
}
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 = <A>(error: Object, response: A)
// declare export type EthereumContractWatcherT = (options: {
// fromBlock?: EthereumBlockNumberT,
// toBlock?: EthereumBlockNumberT,
// address?: EthereumAddressT
// }) => *
// end contract data
}

@ -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<T_DEVICE>;

@ -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<EthereumAddressT>) => void) => void,
sign: (payload: string, signer: EthereumAddressT) => Promise<string>,
contract: (abi: Array<Object>) => 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>) => void,
stopWatching: (callback: any) => void,
}
declare export class ContractFactory {
// constructor(abi: Array<Object>);
eth: Eth;
abi: Array<Object>;
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' {
};
}
}
}
}
*/

@ -31,7 +31,10 @@ export const initialState: State = {
defaultGasLimit: 0,
defaultGasLimitTokens: 0,
defaultGasPrice: 0,
explorer: '',
explorer: {
tx: '',
address: ''
},
tokens: '',
backends: []
},

@ -13,9 +13,15 @@ export type Coin = {
defaultGasLimit: number;
defaultGasLimitTokens: number;
defaultGasPrice: number;
explorer: string;
explorer: {
tx: string;
address: string;
};
tokens: string;
backends: Array<any>
backends: Array<{
name: string;
urls: Array<string>;
}>
}
export type NetworkToken = {

@ -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;

@ -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,

@ -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;

@ -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;
}

@ -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<string> = [
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;

@ -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) );
}
}

@ -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,

@ -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<string> = ['LOG_TO_EXCLUDE'];
const pass: Array<string> = 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<string> = ['LOG_TO_EXCLUDE', 'log__add'];
const pass: Array<string> = 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,

@ -43,6 +43,7 @@
height: 200px;
min-height: 200px;
resize: vertical;
font-size: 10px;
&:focus {
box-shadow: none;
}

@ -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;
}
}

Loading…
Cancel
Save