mirror of
https://github.com/trezor/trezor-wallet
synced 2024-12-30 19:00:53 +00:00
device clone, device connect priority + BIG refactoring for
components/containers
This commit is contained in:
parent
1e316ea9d2
commit
60ead5a452
@ -46,7 +46,7 @@
|
|||||||
{
|
{
|
||||||
"name": "Ethereum Classic",
|
"name": "Ethereum Classic",
|
||||||
"symbol": "ETC",
|
"symbol": "ETC",
|
||||||
"network": "ethereumclassic",
|
"network": "ethereum-classic",
|
||||||
"bip44": "m/44'/61'/0'/0",
|
"bip44": "m/44'/61'/0'/0",
|
||||||
"defaultGasPrice": 64,
|
"defaultGasPrice": 64,
|
||||||
"defaultGasLimit": 21000,
|
"defaultGasLimit": 21000,
|
||||||
|
0
src/js/actions/DiscoveryActions.js
Normal file
0
src/js/actions/DiscoveryActions.js
Normal file
@ -41,9 +41,6 @@ export function loadTokensFromJSON(): any {
|
|||||||
return collection;
|
return collection;
|
||||||
}, Promise.resolve({}));
|
}, Promise.resolve({}));
|
||||||
|
|
||||||
console.log("JADE DAL")
|
|
||||||
|
|
||||||
|
|
||||||
const devices: ?string = get('devices');
|
const devices: ?string = get('devices');
|
||||||
if (devices) {
|
if (devices) {
|
||||||
dispatch({
|
dispatch({
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import TrezorConnect, { UI, UI_EVENT } from 'trezor-connect';
|
import TrezorConnect, { UI, UI_EVENT } from 'trezor-connect';
|
||||||
import * as ACTIONS from './index';
|
|
||||||
import * as MODAL from './constants/Modal';
|
import * as MODAL from './constants/Modal';
|
||||||
import * as CONNECT from './constants/TrezorConnect';
|
import * as CONNECT from './constants/TrezorConnect';
|
||||||
|
|
||||||
@ -10,7 +9,7 @@ import * as CONNECT from './constants/TrezorConnect';
|
|||||||
export function onPinSubmit(value: string): any {
|
export function onPinSubmit(value: string): any {
|
||||||
TrezorConnect.uiResponse({ type: UI.RECEIVE_PIN, payload: value });
|
TrezorConnect.uiResponse({ type: UI.RECEIVE_PIN, payload: value });
|
||||||
return {
|
return {
|
||||||
type: ACTIONS.CLOSE_MODAL
|
type: MODAL.CLOSE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,7 +24,7 @@ export function onPassphraseSubmit(passphrase: string): any {
|
|||||||
});
|
});
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ACTIONS.CLOSE_MODAL
|
type: MODAL.CLOSE
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,7 +59,7 @@ export const onForgetSingleDevice = (device: any) => {
|
|||||||
|
|
||||||
export const onCancel = () => {
|
export const onCancel = () => {
|
||||||
return {
|
return {
|
||||||
type: ACTIONS.CLOSE_MODAL
|
type: MODAL.CLOSE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
24
src/js/actions/NotificationActions.js
Normal file
24
src/js/actions/NotificationActions.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/* @flow */
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import * as NOTIFICATION from './constants/notification';
|
||||||
|
|
||||||
|
|
||||||
|
// called from RouterService
|
||||||
|
export const clear = (currentParams, requestedParams): any => {
|
||||||
|
return async (dispatch, getState) => {
|
||||||
|
// if route has been changed from device view into something else (like other device, settings...)
|
||||||
|
// try to remove all Notifications which are linked to previous device (they are not cancelable by user)
|
||||||
|
if (currentParams.device !== requestedParams.device || currentParams.deviceInstance !== requestedParams.deviceInstance) {
|
||||||
|
const entries = getState().notifications.filter(entry => typeof entry.devicePath === 'string');
|
||||||
|
entries.forEach(entry => {
|
||||||
|
dispatch({
|
||||||
|
type: NOTIFICATION.CLOSE,
|
||||||
|
payload: {
|
||||||
|
devicePath: entry.devicePath
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -21,6 +21,8 @@ export const init = (): any => {
|
|||||||
const state: State = {
|
const state: State = {
|
||||||
...initialState,
|
...initialState,
|
||||||
deviceState: selected.state,
|
deviceState: selected.state,
|
||||||
|
deviceId: selected.features.device_id,
|
||||||
|
deviceInstance: selected.instance,
|
||||||
accountIndex: parseInt(urlParams.address),
|
accountIndex: parseInt(urlParams.address),
|
||||||
network: urlParams.network,
|
network: urlParams.network,
|
||||||
location: location.pathname,
|
location: location.pathname,
|
||||||
@ -67,9 +69,10 @@ export const showAddress = (address_n: string): any => {
|
|||||||
const selected = findSelectedDevice(getState().connect);
|
const selected = findSelectedDevice(getState().connect);
|
||||||
if (!selected) return;
|
if (!selected) return;
|
||||||
|
|
||||||
if (selected && !selected.connected) {
|
if (selected && (!selected.connected || !selected.available)) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: RECEIVE.REQUEST_UNVERIFIED,
|
type: RECEIVE.REQUEST_UNVERIFIED,
|
||||||
|
device: selected
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -117,6 +117,8 @@ export const init = (): any => {
|
|||||||
const state: State = {
|
const state: State = {
|
||||||
...initialState,
|
...initialState,
|
||||||
deviceState: selected.state,
|
deviceState: selected.state,
|
||||||
|
deviceId: selected.features.device_id,
|
||||||
|
deviceInstance: selected.instance,
|
||||||
accountIndex: parseInt(urlParams.address),
|
accountIndex: parseInt(urlParams.address),
|
||||||
network: urlParams.network,
|
network: urlParams.network,
|
||||||
coinSymbol: coin.symbol,
|
coinSymbol: coin.symbol,
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import EthereumjsUtil from 'ethereumjs-util';
|
import EthereumjsUtil from 'ethereumjs-util';
|
||||||
import * as ACTIONS from './index';
|
|
||||||
import * as SUMMARY from './constants/summary';
|
import * as SUMMARY from './constants/summary';
|
||||||
import * as TOKEN from './constants/Token';
|
import * as TOKEN from './constants/Token';
|
||||||
import * as ADDRESS from './constants/Address';
|
import * as ADDRESS from './constants/Address';
|
||||||
@ -20,11 +19,13 @@ export const init = (): any => {
|
|||||||
const urlParams = location.params;
|
const urlParams = location.params;
|
||||||
|
|
||||||
const selected = findSelectedDevice( getState().connect );
|
const selected = findSelectedDevice( getState().connect );
|
||||||
if (!selected) return;
|
if (!selected || !selected.state) return;
|
||||||
|
|
||||||
const state: State = {
|
const state: State = {
|
||||||
...initialState,
|
...initialState,
|
||||||
deviceState: selected.state,
|
deviceState: selected.state,
|
||||||
|
deviceId: selected.features.device_id,
|
||||||
|
deviceInstance: selected.instance,
|
||||||
accountIndex: parseInt(urlParams.address),
|
accountIndex: parseInt(urlParams.address),
|
||||||
network: urlParams.network,
|
network: urlParams.network,
|
||||||
location: location.pathname,
|
location: location.pathname,
|
||||||
@ -46,7 +47,7 @@ export const update = (newProps: any): any => {
|
|||||||
} = getState();
|
} = getState();
|
||||||
|
|
||||||
const isLocationChanged: boolean = router.location.pathname !== summary.location;
|
const isLocationChanged: boolean = router.location.pathname !== summary.location;
|
||||||
if (isLocationChanged) {
|
if (isLocationChanged || !summary.deviceState) {
|
||||||
dispatch( init() );
|
dispatch( init() );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -137,98 +138,3 @@ export const removeToken = (token: any): any => {
|
|||||||
token
|
token
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const onTokenSearch = (search: string): any => {
|
|
||||||
return {
|
|
||||||
type: ACTIONS.TOKENS_SEARCH,
|
|
||||||
search
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const onCustomTokenToggle = (): any => {
|
|
||||||
return {
|
|
||||||
type: ACTIONS.TOKENS_CUSTOM_TOGGLE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const onCustomTokenAddressChange = (value: string): any => {
|
|
||||||
// todo:
|
|
||||||
// -validate address
|
|
||||||
// - if adresss is ok, try to fetch token info
|
|
||||||
// return {
|
|
||||||
// type: ACTIONS.TOKENS_CUSTOM_ADDRESS_CHANGE,
|
|
||||||
// value
|
|
||||||
// }
|
|
||||||
|
|
||||||
return async (dispatch, getState) => {
|
|
||||||
|
|
||||||
const valid: boolean = EthereumjsUtil.isValidAddress(value);
|
|
||||||
if (valid) {
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.TOKENS_CUSTOM_ADDRESS_CHANGE,
|
|
||||||
value,
|
|
||||||
valid,
|
|
||||||
fetching: true
|
|
||||||
});
|
|
||||||
|
|
||||||
const { web3, abi } = getState().web3;
|
|
||||||
const contract = web3.eth.contract(abi).at(value);
|
|
||||||
|
|
||||||
contract.name.call((error, name) => {
|
|
||||||
if (error) {
|
|
||||||
// TODO: skip
|
|
||||||
}
|
|
||||||
contract.symbol.call((error, symbol) => {
|
|
||||||
if (error) {
|
|
||||||
// TODO: skip
|
|
||||||
}
|
|
||||||
|
|
||||||
contract.decimals.call((error, decimals) => {
|
|
||||||
console.log("fetched!", name, symbol, decimals)
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
} else {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.TOKENS_CUSTOM_ADDRESS_CHANGE,
|
|
||||||
value,
|
|
||||||
valid
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("VALID!!!", valid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const onCustomTokenNameChange = (value: string): any => {
|
|
||||||
return {
|
|
||||||
type: ACTIONS.TOKENS_CUSTOM_NAME_CHANGE,
|
|
||||||
value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const onCustomTokenShortcutChange = (value: string): any => {
|
|
||||||
return {
|
|
||||||
type: ACTIONS.TOKENS_CUSTOM_SHORTCUT_CHANGE,
|
|
||||||
value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const onCustomTokenDecimalChange = (value: string): any => {
|
|
||||||
return {
|
|
||||||
type: ACTIONS.TOKENS_CUSTOM_DECIMAL_CHANGE,
|
|
||||||
value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const onCustomTokenAdd = (): any => {
|
|
||||||
return {
|
|
||||||
type: ACTIONS.TOKENS_CUSTOM_ADD
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,20 +2,18 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import TrezorConnect, { UI, DEVICE, DEVICE_EVENT, UI_EVENT, TRANSPORT_EVENT } from 'trezor-connect';
|
import TrezorConnect, { UI, DEVICE, DEVICE_EVENT, UI_EVENT, TRANSPORT_EVENT } from 'trezor-connect';
|
||||||
import * as ACTIONS from './index';
|
|
||||||
import * as ADDRESS from './constants/Address';
|
import * as ADDRESS from './constants/Address';
|
||||||
import * as TOKEN from './constants/Token';
|
import * as TOKEN from './constants/Token';
|
||||||
import * as CONNECT from './constants/TrezorConnect';
|
import * as CONNECT from './constants/TrezorConnect';
|
||||||
import * as DISCOVERY from './constants/Discovery';
|
import * as DISCOVERY from './constants/Discovery';
|
||||||
import * as NOTIFICATION from './constants/notification';
|
import * as NOTIFICATION from './constants/notification';
|
||||||
|
import * as WALLET from './constants/wallet';
|
||||||
|
|
||||||
import HDKey from 'hdkey';
|
import HDKey from 'hdkey';
|
||||||
import EthereumjsUtil from 'ethereumjs-util';
|
import EthereumjsUtil from 'ethereumjs-util';
|
||||||
import EthereumjsTx from 'ethereumjs-tx';
|
import EthereumjsTx from 'ethereumjs-tx';
|
||||||
|
|
||||||
//import { getBalance } from '../services/Web3Service';
|
|
||||||
import { getBalance } from './Web3Actions';
|
import { getBalance } from './Web3Actions';
|
||||||
import { getTransactionHistory } from '../services/EtherscanService';
|
|
||||||
|
|
||||||
import { push } from 'react-router-redux';
|
import { push } from 'react-router-redux';
|
||||||
|
|
||||||
@ -24,7 +22,7 @@ import { init as initWeb3, getNonceAsync, getBalanceAsync, getTokenBalanceAsync
|
|||||||
import type { Discovery } from '../reducers/DiscoveryReducer';
|
import type { Discovery } from '../reducers/DiscoveryReducer';
|
||||||
import { resolveAfter } from '../utils/promiseUtils';
|
import { resolveAfter } from '../utils/promiseUtils';
|
||||||
import { getAccounts } from '../utils/reducerUtils';
|
import { getAccounts } from '../utils/reducerUtils';
|
||||||
import { findSelectedDevice, isSavedDevice } from '../reducers/TrezorConnectReducer';
|
import { findSelectedDevice, isSavedDevice, TrezorDevice } from '../reducers/TrezorConnectReducer';
|
||||||
|
|
||||||
export const init = (): any => {
|
export const init = (): any => {
|
||||||
return async (dispatch, getState): Promise<void> => {
|
return async (dispatch, getState): Promise<void> => {
|
||||||
@ -57,15 +55,18 @@ export const init = (): any => {
|
|||||||
await TrezorConnect.init({
|
await TrezorConnect.init({
|
||||||
transportReconnect: true,
|
transportReconnect: true,
|
||||||
connectSrc: 'https://localhost:8088/',
|
connectSrc: 'https://localhost:8088/',
|
||||||
|
// connectSrc: 'https://connect.trezor.io/tpm/',
|
||||||
// connectSrc: 'https://sisyfos.trezor.io/',
|
// connectSrc: 'https://sisyfos.trezor.io/',
|
||||||
debug: true,
|
debug: true,
|
||||||
popup: false,
|
popup: false,
|
||||||
webusb: false
|
webusb: true
|
||||||
});
|
});
|
||||||
|
|
||||||
setTimeout(() => {
|
// wait for init
|
||||||
dispatch( initWeb3() );
|
|
||||||
}, 2000)
|
// setTimeout(() => {
|
||||||
|
// dispatch( initWeb3() );
|
||||||
|
//}, 2000)
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
dispatch({
|
dispatch({
|
||||||
@ -102,37 +103,53 @@ export const postInit = (): any => {
|
|||||||
// devices were connected before Web3 initialized. force DEVICE.CONNECT event on them
|
// devices were connected before Web3 initialized. force DEVICE.CONNECT event on them
|
||||||
const { devices } = getState().connect;
|
const { devices } = getState().connect;
|
||||||
|
|
||||||
|
|
||||||
|
const { initialPathname, initialParams } = getState().wallet
|
||||||
|
if (initialPathname) {
|
||||||
|
dispatch({
|
||||||
|
type: WALLET.SET_INITIAL_URL,
|
||||||
|
pathname: null,
|
||||||
|
params: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (devices.length > 0) {
|
if (devices.length > 0) {
|
||||||
const unacquired = devices.find(d => d.unacquired);
|
const unacquired = devices.find(d => d.unacquired);
|
||||||
if (unacquired) {
|
if (unacquired) {
|
||||||
handleDeviceConnect(unacquired);
|
dispatch( onSelectDevice(unacquired) );
|
||||||
} else {
|
} else {
|
||||||
const latest = devices.sort((a, b) => {
|
const latest: Array<TrezorDevice> = sortDevices(devices);
|
||||||
if (!a.ts || !b.ts) {
|
const firstConnected: ?TrezorDevice = latest.find(d => d.connected);
|
||||||
return -1;
|
dispatch( onSelectDevice(firstConnected || latest[0]) );
|
||||||
} else {
|
|
||||||
return a.ts > b.ts ? 1 : -1;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log("LATEST", latest)
|
// TODO
|
||||||
|
if (initialParams) {
|
||||||
|
if (!initialParams.hasOwnProperty("network") && initialPathname !== getState().router.location.pathname) {
|
||||||
|
// dispatch( push(initialPathname) );
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let d of devices) {
|
|
||||||
handleDeviceConnect(d);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const initConnectedDevice = (device: any): any => {
|
const sortDevices = (devices: Array<TrezorDevice>): Array<TrezorDevice> => {
|
||||||
|
return devices.sort((a, b) => {
|
||||||
|
if (!a.ts || !b.ts) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return a.ts > b.ts ? -1 : 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const initConnectedDevice = (device: any, force): any => {
|
||||||
return (dispatch, getState): void => {
|
return (dispatch, getState): void => {
|
||||||
|
|
||||||
//dispatch( onSelectDevice(device) );
|
|
||||||
|
|
||||||
const selected = findSelectedDevice(getState().connect);
|
const selected = findSelectedDevice(getState().connect);
|
||||||
if (selected && selected.state) {
|
if (!selected || (selected && selected.state)) {
|
||||||
dispatch( onSelectDevice(device) );
|
|
||||||
} else if (!selected) {
|
|
||||||
dispatch( onSelectDevice(device) );
|
dispatch( onSelectDevice(device) );
|
||||||
}
|
}
|
||||||
// if (device.unacquired && selected && selected.path !== device.path && !selected.connected) {
|
// if (device.unacquired && selected && selected.path !== device.path && !selected.connected) {
|
||||||
@ -143,11 +160,19 @@ export const initConnectedDevice = (device: any): any => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// selection from Aside dropdown
|
// selection from Aside dropdown button
|
||||||
|
// after device_connect event
|
||||||
// or after acquiring device
|
// or after acquiring device
|
||||||
export function onSelectDevice(device: any): any {
|
// device type could be local TrezorDevice or Device (from trezor-connect device_connect event)
|
||||||
|
export const onSelectDevice = (device: any): any => {
|
||||||
return (dispatch, getState): void => {
|
return (dispatch, getState): void => {
|
||||||
// || device.isUsedElsewhere
|
// || device.isUsedElsewhere
|
||||||
|
|
||||||
|
console.log("------> REDITTO", device, getState().wallet.initialUrl);
|
||||||
|
|
||||||
|
// switch to initial url and reset this value
|
||||||
|
|
||||||
|
|
||||||
if (device.unacquired) {
|
if (device.unacquired) {
|
||||||
dispatch( push(`/device/${ device.path }/acquire`) );
|
dispatch( push(`/device/${ device.path }/acquire`) );
|
||||||
} else if (device.features.bootloader_mode) {
|
} else if (device.features.bootloader_mode) {
|
||||||
@ -155,58 +180,50 @@ export function onSelectDevice(device: any): any {
|
|||||||
} else if (device.instance) {
|
} else if (device.instance) {
|
||||||
dispatch( push(`/device/${ device.features.device_id }:${ device.instance }`) );
|
dispatch( push(`/device/${ device.features.device_id }:${ device.instance }`) );
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
const urlParams: any = getState().router.location.params;
|
||||||
|
// let url: string = `/device/${ device.features.device_id }/network/ethereum/address/0`;
|
||||||
|
let url: string = `/device/${ device.features.device_id }`;
|
||||||
|
let instance: ?string;
|
||||||
|
// check if device is not TrezorDevice type
|
||||||
|
if (!device.hasOwnProperty('ts')) {
|
||||||
|
// its device from trezor-connect (called in initConnectedDevice triggered by device_connect event)
|
||||||
|
// need to lookup if there are unavailable instances
|
||||||
|
const available: Array<TrezorDevice> = getState().connect.devices.filter(d => d.path === device.path);
|
||||||
|
const latest: Array<TrezorDevice> = sortDevices(available);
|
||||||
|
|
||||||
|
if (latest.length > 0 && latest[0].instance) {
|
||||||
|
url += `:${ latest[0].instance }`;
|
||||||
|
instance = latest[0].instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// check if current location is not set to this device
|
||||||
//dispatch( push(`/device/${ device.features.device_id }/network/etc/address/0`) );
|
//dispatch( push(`/device/${ device.features.device_id }/network/etc/address/0`) );
|
||||||
dispatch( push(`/device/${ device.features.device_id }`) );
|
|
||||||
|
if (urlParams.deviceInstance !== instance || urlParams.device !== device.features.device_id) {
|
||||||
|
dispatch( push(url) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: as TrezorConnect method
|
|
||||||
const __getDeviceState = async (path, instance, state): Promise<any> => {
|
|
||||||
// return await TrezorConnect.getPublicKey({
|
|
||||||
// device: {
|
|
||||||
// path,
|
|
||||||
// instance
|
|
||||||
// },
|
|
||||||
// path: "m/1'/0'/0'",
|
|
||||||
// confirmation: false
|
|
||||||
// });
|
|
||||||
|
|
||||||
return await TrezorConnect.getDeviceState({
|
|
||||||
device: {
|
|
||||||
path,
|
|
||||||
instance,
|
|
||||||
state
|
|
||||||
},
|
|
||||||
path: "m/1'/0'/0'",
|
|
||||||
confirmation: false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export const switchToFirstAvailableDevice = (): any => {
|
export const switchToFirstAvailableDevice = (): any => {
|
||||||
return async (dispatch, getState): Promise<void> => {
|
return async (dispatch, getState): Promise<void> => {
|
||||||
|
|
||||||
const { devices } = getState().connect;
|
const { devices } = getState().connect;
|
||||||
if (devices.length > 0) {
|
if (devices.length > 0) {
|
||||||
// TODO: Priority:
|
// TODO: Priority:
|
||||||
// 1. Unacquired
|
// 1. First Unacquired
|
||||||
// 2. First connected
|
// 2. First connected
|
||||||
// 3. Saved with latest timestamp
|
// 3. Saved with latest timestamp
|
||||||
// 4. First from the list
|
|
||||||
const unacquired = devices.find(d => d.unacquired);
|
const unacquired = devices.find(d => d.unacquired);
|
||||||
if (unacquired) {
|
if (unacquired) {
|
||||||
dispatch( initConnectedDevice(unacquired) );
|
dispatch( initConnectedDevice(unacquired) );
|
||||||
} else {
|
} else {
|
||||||
const latest = devices.sort((a, b) => {
|
const latest: Array<TrezorDevice> = sortDevices(devices);
|
||||||
if (!a.ts || !b.ts) {
|
const firstConnected: ?TrezorDevice = latest.find(d => d.connected);
|
||||||
return -1;
|
dispatch( onSelectDevice(firstConnected || latest[0]) );
|
||||||
} else {
|
|
||||||
return a.ts > b.ts ? 1 : -1;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
dispatch( initConnectedDevice(devices[0]) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
dispatch( push('/') );
|
dispatch( push('/') );
|
||||||
dispatch({
|
dispatch({
|
||||||
@ -217,17 +234,24 @@ export const switchToFirstAvailableDevice = (): any => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const getSelectedDeviceState = (): any => {
|
export const getSelectedDeviceState = (): any => {
|
||||||
return async (dispatch, getState): Promise<void> => {
|
return async (dispatch, getState): Promise<void> => {
|
||||||
const selected = findSelectedDevice(getState().connect);
|
const selected = findSelectedDevice(getState().connect);
|
||||||
console.warn("init selected", selected)
|
console.warn("init selected", selected)
|
||||||
if (selected
|
if (selected
|
||||||
&& selected.connected
|
&& selected.connected
|
||||||
&& !selected.unacquired
|
&& selected.features
|
||||||
&& !selected.acquiring
|
&& !selected.acquiring
|
||||||
&& !selected.state) {
|
&& !selected.state) {
|
||||||
|
|
||||||
const response = await __getDeviceState(selected.path, selected.instance, selected.state);
|
const response = await TrezorConnect.getDeviceState({
|
||||||
|
device: {
|
||||||
|
path: selected.path,
|
||||||
|
instance: selected.instance,
|
||||||
|
state: selected.state
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (response && response.success) {
|
if (response && response.success) {
|
||||||
dispatch({
|
dispatch({
|
||||||
@ -239,20 +263,25 @@ export const getSelectedDeviceState = (): any => {
|
|||||||
dispatch({
|
dispatch({
|
||||||
type: NOTIFICATION.ADD,
|
type: NOTIFICATION.ADD,
|
||||||
payload: {
|
payload: {
|
||||||
|
devicePath: selected.path,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
title: 'Authentification error',
|
title: 'Authentication error',
|
||||||
message: response.payload.error,
|
message: response.payload.error,
|
||||||
cancelable: true,
|
cancelable: false,
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
label: 'Try again',
|
label: 'Try again',
|
||||||
callback: () => {
|
callback: () => {
|
||||||
|
dispatch( {
|
||||||
|
type: NOTIFICATION.CLOSE,
|
||||||
|
payload: { devicePath: selected.path }
|
||||||
|
});
|
||||||
dispatch( getSelectedDeviceState() );
|
dispatch( getSelectedDeviceState() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -273,7 +302,7 @@ export const deviceDisconnect = (device: any): any => {
|
|||||||
dispatch({
|
dispatch({
|
||||||
type: CONNECT.REMEMBER_REQUEST,
|
type: CONNECT.REMEMBER_REQUEST,
|
||||||
device,
|
device,
|
||||||
allInstances: affected
|
instances: affected
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -296,22 +325,26 @@ export const coinChanged = (network: ?string): any => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function reload(): any {
|
||||||
|
return async (dispatch, getState) => {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function acquire(): any {
|
export function acquire(): any {
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
|
|
||||||
const selected = findSelectedDevice(getState().connect);
|
const selected = findSelectedDevice(getState().connect);
|
||||||
|
|
||||||
const saved = getState().connect.devices.map(d => {
|
// const saved = getState().connect.devices.map(d => {
|
||||||
if (d.state) {
|
// if (d.state) {
|
||||||
return {
|
// return {
|
||||||
instance: d.instance,
|
// instance: d.instance,
|
||||||
state: d.state
|
// state: d.state
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
//const response = await __acquire(selected.path, selected.instance);
|
//const response = await __acquire(selected.path, selected.instance);
|
||||||
|
|
||||||
@ -374,6 +407,12 @@ export const forgetDevice = (device: any) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const gotoDeviceSettings = (device: any) => {
|
||||||
|
return (dispatch: any, getState: any): any => {
|
||||||
|
dispatch( push(`/device/${ device.features.device_id }/settings`) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// called from Aside - device menu (forget single instance)
|
// called from Aside - device menu (forget single instance)
|
||||||
export const forget = (device: any) => {
|
export const forget = (device: any) => {
|
||||||
return {
|
return {
|
||||||
@ -404,6 +443,12 @@ export const beginDiscoveryProcess = (device: any, network: string): any => {
|
|||||||
const { config } = getState().localStorage;
|
const { config } = getState().localStorage;
|
||||||
const coinToDiscover = config.coins.find(c => c.network === network);
|
const coinToDiscover = config.coins.find(c => c.network === network);
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: DISCOVERY.WAITING,
|
||||||
|
device,
|
||||||
|
network
|
||||||
|
});
|
||||||
|
|
||||||
// TODO: validate device deviceState
|
// TODO: validate device deviceState
|
||||||
// const deviceState = await __acquire(device.path, device.instance);
|
// const deviceState = await __acquire(device.path, device.instance);
|
||||||
// if (deviceState && deviceState.success) {
|
// if (deviceState && deviceState.success) {
|
||||||
@ -425,9 +470,10 @@ export const beginDiscoveryProcess = (device: any, network: string): any => {
|
|||||||
keepSession: true // acquire and hold session
|
keepSession: true // acquire and hold session
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// handle TREZOR response error
|
||||||
if (!response.success) {
|
if (!response.success) {
|
||||||
// TODO: check message
|
// TODO: check message
|
||||||
console.warn("DISCO ERROR", response)
|
console.warn("DISCOVERY ERROR", response)
|
||||||
dispatch({
|
dispatch({
|
||||||
type: NOTIFICATION.ADD,
|
type: NOTIFICATION.ADD,
|
||||||
payload: {
|
payload: {
|
||||||
@ -448,9 +494,10 @@ export const beginDiscoveryProcess = (device: any, network: string): any => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check for interruption
|
// check for interruption
|
||||||
|
let discoveryProcess: ?Discovery = getState().discovery.find(d => d.deviceState === device.state && d.network === network);
|
||||||
|
if (discoveryProcess && discoveryProcess.interrupted) return;
|
||||||
|
|
||||||
// TODO: handle response error
|
|
||||||
const basePath: Array<number> = response.payload.path;
|
const basePath: Array<number> = response.payload.path;
|
||||||
const hdKey = new HDKey();
|
const hdKey = new HDKey();
|
||||||
hdKey.publicKey = new Buffer(response.payload.publicKey, 'hex');
|
hdKey.publicKey = new Buffer(response.payload.publicKey, 'hex');
|
||||||
@ -502,6 +549,15 @@ export const discoverAddress = (device: any, discoveryProcess: Discovery): any =
|
|||||||
});
|
});
|
||||||
if (discoveryProcess.interrupted) return;
|
if (discoveryProcess.interrupted) return;
|
||||||
|
|
||||||
|
// const discoveryA = await TrezorConnect.accountDiscovery({
|
||||||
|
// device: {
|
||||||
|
// path: device.path,
|
||||||
|
// instance: device.instance,
|
||||||
|
// state: device.state
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
// if (discoveryProcess.interrupted) return;
|
||||||
|
|
||||||
if (verifyAddress && verifyAddress.success) {
|
if (verifyAddress && verifyAddress.success) {
|
||||||
//const trezorAddress: string = '0x' + verifyAddress.payload.address;
|
//const trezorAddress: string = '0x' + verifyAddress.payload.address;
|
||||||
const trezorAddress: string = EthereumjsUtil.toChecksumAddress(verifyAddress.payload.address);
|
const trezorAddress: string = EthereumjsUtil.toChecksumAddress(verifyAddress.payload.address);
|
||||||
@ -630,6 +686,9 @@ export function startDiscoveryProcess(device: any, network: string, ignoreComple
|
|||||||
} else if (!selected.state) {
|
} else if (!selected.state) {
|
||||||
console.warn("Start discovery: Selected device wasn't authenticated yet...")
|
console.warn("Start discovery: Selected device wasn't authenticated yet...")
|
||||||
return;
|
return;
|
||||||
|
} else if (selected.connected && !selected.available) {
|
||||||
|
console.warn("Start discovery: Selected device is unavailable...")
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const discovery = getState().discovery;
|
const discovery = getState().discovery;
|
||||||
@ -679,8 +738,8 @@ export const restoreDiscovery = (): any => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// there is no discovery process but it should be
|
// there is no discovery process but it should be
|
||||||
// this is possible race condition when "network" was changed in url but device wasn't authenticated yet
|
// this is possible race condition when "network" was changed in url but device was not authenticated yet
|
||||||
// try to discovery after CONNECT.AUTH_DEVICE action
|
// try to start discovery after CONNECT.AUTH_DEVICE action
|
||||||
export const checkDiscoveryStatus = (): any => {
|
export const checkDiscoveryStatus = (): any => {
|
||||||
return (dispatch, getState): void => {
|
return (dispatch, getState): void => {
|
||||||
const selected = findSelectedDevice(getState().connect);
|
const selected = findSelectedDevice(getState().connect);
|
||||||
|
@ -2,9 +2,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
export const ON_RESIZE: string = 'ON_RESIZE';
|
export const ON_RESIZE: string = 'ON_RESIZE';
|
||||||
export const ON_BEFORE_UNLOAD: string = 'app__on_before_unload';
|
|
||||||
export const TOGGLE_DEVICE_DROPDOWN: string = 'TOGGLE_DEVICE_DROPDOWN';
|
export const TOGGLE_DEVICE_DROPDOWN: string = 'TOGGLE_DEVICE_DROPDOWN';
|
||||||
export const RESIZE_CONTAINER: string = 'RESIZE_CONTAINER';
|
import * as WALLET from './constants/wallet';
|
||||||
|
|
||||||
export const onResize = (): any => {
|
export const onResize = (): any => {
|
||||||
return {
|
return {
|
||||||
@ -14,20 +13,13 @@ export const onResize = (): any => {
|
|||||||
|
|
||||||
export const onBeforeUnload = (): any => {
|
export const onBeforeUnload = (): any => {
|
||||||
return {
|
return {
|
||||||
type: ON_BEFORE_UNLOAD
|
type: WALLET.ON_BEFORE_UNLOAD
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const resizeAppContainer = (opened: boolean): any => {
|
|
||||||
return {
|
|
||||||
type: RESIZE_CONTAINER,
|
|
||||||
opened
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const toggleDeviceDropdown = (opened: boolean): any => {
|
export const toggleDeviceDropdown = (opened: boolean): any => {
|
||||||
return {
|
return {
|
||||||
type: TOGGLE_DEVICE_DROPDOWN,
|
type: WALLET.TOGGLE_DEVICE_DROPDOWN,
|
||||||
opened
|
opened
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,10 +7,8 @@ import EthereumjsUtil from 'ethereumjs-util';
|
|||||||
import EthereumjsTx from 'ethereumjs-tx';
|
import EthereumjsTx from 'ethereumjs-tx';
|
||||||
import TrezorConnect from 'trezor-connect';
|
import TrezorConnect from 'trezor-connect';
|
||||||
import { strip } from '../utils/ethUtils';
|
import { strip } from '../utils/ethUtils';
|
||||||
import * as ACTIONS from './index';
|
|
||||||
import * as ADDRESS from './constants/Address';
|
import * as ADDRESS from './constants/Address';
|
||||||
import * as WEB3 from './constants/Web3';
|
import * as WEB3 from './constants/Web3';
|
||||||
import { loadHistory } from '../services/EtherscanService';
|
|
||||||
import { httpRequest } from '../utils/networkUtils';
|
import { httpRequest } from '../utils/networkUtils';
|
||||||
|
|
||||||
type ActionMethod = (dispatch: any, getState: any) => Promise<any>;
|
type ActionMethod = (dispatch: any, getState: any) => Promise<any>;
|
||||||
@ -192,9 +190,6 @@ export function init(web3: ?Web3, coinIndex: number = 0): ActionMethod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function initBlockTicker() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export function initContracts(): ActionMethod {
|
export function initContracts(): ActionMethod {
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
@ -241,14 +236,17 @@ export function getGasPrice(network: string): ActionMethod {
|
|||||||
|
|
||||||
const index: number = getState().web3.findIndex(w3 => w3.network === network);
|
const index: number = getState().web3.findIndex(w3 => w3.network === network);
|
||||||
|
|
||||||
const web3 = getState().web3[ index ].web3;
|
const web3instance = getState().web3[ index ];
|
||||||
|
const web3 = web3instance.web3;
|
||||||
web3.eth.getGasPrice((error, gasPrice) => {
|
web3.eth.getGasPrice((error, gasPrice) => {
|
||||||
if (!error) {
|
if (!error) {
|
||||||
dispatch({
|
if (web3instance.gasPrice && web3instance.gasPrice.toString() !== gasPrice.toString()) {
|
||||||
type: WEB3.GAS_PRICE_UPDATED,
|
dispatch({
|
||||||
network: network,
|
type: WEB3.GAS_PRICE_UPDATED,
|
||||||
gasPrice
|
network: network,
|
||||||
});
|
gasPrice
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -313,7 +311,6 @@ export function getTransactionReceipt(tx: any): any {
|
|||||||
web3.eth.getBlock(receipt.blockHash, (error, block) => {
|
web3.eth.getBlock(receipt.blockHash, (error, block) => {
|
||||||
console.log("---MAMM BLOCK", error, block, receipt, receipt.blockHash)
|
console.log("---MAMM BLOCK", error, block, receipt, receipt.blockHash)
|
||||||
dispatch({
|
dispatch({
|
||||||
//type: ACTIONS.TX_CONFIRMED,
|
|
||||||
type: WEB3.PENDING_TX_RESOLVED,
|
type: WEB3.PENDING_TX_RESOLVED,
|
||||||
tx,
|
tx,
|
||||||
receipt,
|
receipt,
|
||||||
|
@ -11,3 +11,4 @@ export const FORGET: string = 'modal__forget';
|
|||||||
export const REMEMBER: string = 'modal__remember';
|
export const REMEMBER: string = 'modal__remember';
|
||||||
export const ON_FORGET: string = 'modal__on_forget';
|
export const ON_FORGET: string = 'modal__on_forget';
|
||||||
export const ON_REMEMBER: string = 'modal__on_remember';
|
export const ON_REMEMBER: string = 'modal__on_remember';
|
||||||
|
export const CLOSE: string = 'modal__close';
|
||||||
|
6
src/js/actions/constants/wallet.js
Normal file
6
src/js/actions/constants/wallet.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
/* @flow */
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
export const ON_BEFORE_UNLOAD: string = 'wallet__on_before_unload';
|
||||||
|
export const TOGGLE_DEVICE_DROPDOWN: string = 'wallet_toggle_dropdown';
|
||||||
|
export const SET_INITIAL_URL: string = 'wallet_set_initial_url';
|
@ -1,45 +0,0 @@
|
|||||||
/* @flow */
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
export const CLOSE_MODAL: string = 'action__close_modal';
|
|
||||||
|
|
||||||
export const ON_PIN_SUBMIT: string = 'action__on_pin_submit';
|
|
||||||
|
|
||||||
export const ON_PASSPHRASE_SUBMIT: string = 'action__on_passphrase_submit';
|
|
||||||
|
|
||||||
|
|
||||||
export const ON_ADDRESS_CHANGE: string = 'send__on_address_change';
|
|
||||||
export const ON_AMOUNT_CHANGE: string = 'send__on_amount_change';
|
|
||||||
export const ON_FEE_LEVEL_CHANGE: string = 'send__on_fee_level_change';
|
|
||||||
export const ON_GAS_PRICE_CHANGE: string = 'send__on_gas_price_change';
|
|
||||||
export const ON_GAS_LIMIT_CHANGE: string = 'send__on_gas_limit_change';
|
|
||||||
export const ON_TX_DATA_CHANGE: string = 'send__on_data_change';
|
|
||||||
export const ON_TX_SEND: string = 'send__on_send';
|
|
||||||
export const ON_GAS_PRICE_UPDATE: string = 'send__on_gas_price_update';
|
|
||||||
|
|
||||||
|
|
||||||
export const ADDRESS_CREATE: string = 'address__create';
|
|
||||||
export const ADDRESS_DELETE: string = 'address__delete';
|
|
||||||
export const ADDRESS_SET_BALANCE: string = 'address2__set_balance';
|
|
||||||
export const ADDRESS_SET_HISTORY: string = 'address__set_history';
|
|
||||||
export const ADDRESS_UPDATE_BALANCE: string = 'address__update_balance';
|
|
||||||
export const ADDRESS_ADD_TO_HISTORY: string = 'address__add_to_history';
|
|
||||||
|
|
||||||
export const TX_STATUS_OK: string = 'tx__status_ok';
|
|
||||||
export const TX_STATUS_ERROR: string = 'tx__status_error';
|
|
||||||
export const TX_STATUS_UNKNOWN: string = 'tx__status_unknown';
|
|
||||||
export const TX_CONFIRMED: string = 'tx__confirmed';
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const TOKENS_TOGGLE_SUMMARY: string = 'tokens_toggle_summary';
|
|
||||||
|
|
||||||
export const TOKENS_SEARCH: string = 'tokens_search';
|
|
||||||
|
|
||||||
|
|
||||||
export const TOKENS_CUSTOM_TOGGLE: string = 'tokens_custom_toggle';
|
|
||||||
export const TOKENS_CUSTOM_ADDRESS_CHANGE: string = 'tokens_custom_address_change';
|
|
||||||
export const TOKENS_CUSTOM_NAME_CHANGE: string = 'tokens_custom_name_change';
|
|
||||||
export const TOKENS_CUSTOM_SHORTCUT_CHANGE: string = 'tokens_custom_shortcut_change';
|
|
||||||
export const TOKENS_CUSTOM_DECIMAL_CHANGE: string = 'tokens_custom_decimal_change';
|
|
||||||
export const TOKENS_CUSTOM_ADD: string = 'tokens_custom_add';
|
|
@ -26,7 +26,7 @@ export const Notification = (props: any) => {
|
|||||||
) : null }
|
) : null }
|
||||||
<div className="notification-body">
|
<div className="notification-body">
|
||||||
<h2>{ props.title }</h2>
|
<h2>{ props.title }</h2>
|
||||||
<p dangerouslySetInnerHTML={{__html: props.message }}></p>
|
{ props.message ? (<p dangerouslySetInnerHTML={{__html: props.message }}></p>) : null }
|
||||||
</div>
|
</div>
|
||||||
{ props.actions && props.actions.length > 0 ? (
|
{ props.actions && props.actions.length > 0 ? (
|
||||||
<div className="notification-action">
|
<div className="notification-action">
|
||||||
|
@ -6,19 +6,28 @@ import TrezorConnect from 'trezor-connect';
|
|||||||
|
|
||||||
export default class InstallBridge extends Component {
|
export default class InstallBridge extends Component {
|
||||||
|
|
||||||
|
|
||||||
|
componentDidMount(): void {
|
||||||
|
const transport: any = this.props.transport;
|
||||||
|
if (transport && transport.version.indexOf('webusb') >= 0)
|
||||||
|
TrezorConnect.renderWebUSBButton();
|
||||||
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
const transport = this.props.transport;
|
const transport = this.props.transport;
|
||||||
if (transport && transport.type.indexOf('webusb') >= 0)
|
if (transport && transport.version.indexOf('webusb') >= 0)
|
||||||
TrezorConnect.renderWebUSBButton();
|
TrezorConnect.renderWebUSBButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
let css = 'row';
|
||||||
let webusb = null;
|
let webusb = null;
|
||||||
let connectClaim = 'Connect TREZOR to continue';
|
let connectClaim = 'Connect TREZOR to continue';
|
||||||
let and = null;
|
let and = null;
|
||||||
let bridgeClaim = null;
|
let bridgeClaim = null;
|
||||||
const transport = this.props.transport;
|
const transport = this.props.transport;
|
||||||
if (transport && transport.type.indexOf('webusb') >= 0) {
|
if (transport && transport.version.indexOf('webusb') >= 0) {
|
||||||
|
css = 'row webusb'
|
||||||
webusb = <button className="trezor-webusb-button">Check for devices</button>;
|
webusb = <button className="trezor-webusb-button">Check for devices</button>;
|
||||||
connectClaim = 'Connect TREZOR';
|
connectClaim = 'Connect TREZOR';
|
||||||
and = <p>and</p>;
|
and = <p>and</p>;
|
||||||
@ -30,7 +39,7 @@ export default class InstallBridge extends Component {
|
|||||||
<h2 className="claim">The private bank in your hands.</h2>
|
<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 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>
|
<p>TREZOR Wallet allows you to easily control your funds, manage your balance and initiate transfers.</p>
|
||||||
<div className="row">
|
<div className={ css }>
|
||||||
<p className="connect">
|
<p className="connect">
|
||||||
<span>
|
<span>
|
||||||
<svg width="12px" height="35px" viewBox="0 0 20 57">
|
<svg width="12px" height="35px" viewBox="0 0 20 57">
|
||||||
@ -44,8 +53,8 @@ export default class InstallBridge extends Component {
|
|||||||
{ connectClaim }
|
{ connectClaim }
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
{ and }
|
<p className="webusb-and">and</p>
|
||||||
{ webusb }
|
<button className="trezor-webusb-button">Check for devices</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="image">
|
<div className="image">
|
||||||
<p>
|
<p>
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
import Preloader from './Preloader';
|
||||||
import Select from 'react-select';
|
import Select from 'react-select';
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
@ -28,9 +29,9 @@ export default class InstallBridge extends Component {
|
|||||||
|
|
||||||
const currentTarget = installers.find(i => i.id === props.browserState.osname);
|
const currentTarget = installers.find(i => i.id === props.browserState.osname);
|
||||||
this.state = {
|
this.state = {
|
||||||
version: '2.0.11',
|
version: '2.0.12',
|
||||||
target: currentTarget,
|
url: 'https://wallet.trezor.io/data/bridge/2.0.12/',
|
||||||
url: 'https://wallet.trezor.io/data/bridge/2.0.11/'
|
target: null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,11 +41,25 @@ export default class InstallBridge extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
componentWillUpdate() {
|
||||||
|
if (this.props.browserState.osname && !this.state.target) {
|
||||||
|
const currentTarget = installers.find(i => i.id === this.props.browserState.osname);
|
||||||
|
this.setState({
|
||||||
|
target: currentTarget
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
if (!this.state.target) {
|
||||||
|
return <Preloader />;
|
||||||
|
}
|
||||||
|
|
||||||
const url = `${ this.state.url }${ this.state.target.value }`;
|
const url = `${ this.state.url }${ this.state.target.value }`;
|
||||||
return (
|
return (
|
||||||
<main>
|
<main>
|
||||||
<h3 className="claim">TREZOR Bridge. <span>Version 2.0.11</span></h3>
|
<h3 className="claim">TREZOR Bridge. <span>Version 2.0.12</span></h3>
|
||||||
<p>New communication tool to facilitate the connection between your TREZOR and your internet browser.</p>
|
<p>New communication tool to facilitate the connection between your TREZOR and your internet browser.</p>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<Select
|
<Select
|
||||||
|
@ -58,7 +58,7 @@ export default (props: any): any => {
|
|||||||
} else if (connectError || bridgeRoute) {
|
} else if (connectError || bridgeRoute) {
|
||||||
css += ' install-bridge';
|
css += ' install-bridge';
|
||||||
body = <InstallBridge browserState={ props.connect.browserState } />;
|
body = <InstallBridge browserState={ props.connect.browserState } />;
|
||||||
} else if (web3.length > 0 && devices.length < 1) {
|
} else if (props.wallet.ready && devices.length < 1) {
|
||||||
css += ' connect-device';
|
css += ' connect-device';
|
||||||
body = <ConnectDevice transport={ transport } />;
|
body = <ConnectDevice transport={ transport } />;
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,24 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React from 'react';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import LandingPage from '../components/landing/LandingPage';
|
import LandingPage from './LandingPage';
|
||||||
import * as LogActions from '../actions/LogActions';
|
|
||||||
|
|
||||||
function mapStateToProps(state, own) {
|
const mapStateToProps = (state, own) => {
|
||||||
return {
|
return {
|
||||||
localStorage: state.localStorage,
|
localStorage: state.localStorage,
|
||||||
modal: state.modal,
|
modal: state.modal,
|
||||||
web3: state.web3,
|
web3: state.web3,
|
||||||
|
wallet: state.wallet,
|
||||||
connect: state.connect,
|
connect: state.connect,
|
||||||
router: state.router
|
router: state.router
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
return {
|
return {
|
||||||
|
|
||||||
};
|
};
|
@ -38,20 +38,42 @@ export const ConfirmUnverifiedAddress = (props: any): any => {
|
|||||||
showAddress
|
showAddress
|
||||||
} = props.receiveActions;
|
} = props.receiveActions;
|
||||||
|
|
||||||
|
const {
|
||||||
|
device
|
||||||
|
} = props.modal;
|
||||||
|
|
||||||
return (
|
if (!device.connected) {
|
||||||
<div className="confirm-address-unverified">
|
return (
|
||||||
<button className="close-modal transparent" onClick={ onCancel }></button>
|
<div className="confirm-address-unverified">
|
||||||
<h3>Your TREZOR is not connected</h3>
|
<button className="close-modal transparent" onClick={ onCancel }></button>
|
||||||
<p>To prevent phishing attacks, you should verify the address on your TREZOR first. Please reconnect your device to continue with the verification process.</p>
|
<h3>{ device.instanceLabel } is not connected</h3>
|
||||||
<button onClick={ event => {
|
<p>To prevent phishing attacks, you should verify the address on your TREZOR first. Please reconnect your device to continue with the verification process.</p>
|
||||||
onCancel();
|
<button onClick={ event => {
|
||||||
showAddress(account.addressPath);
|
onCancel();
|
||||||
} }>Try again</button>
|
showAddress(account.addressPath);
|
||||||
<button className="white" onClick={ event => {
|
} }>Try again</button>
|
||||||
onCancel();
|
<button className="white" onClick={ event => {
|
||||||
showUnverifiedAddress();
|
onCancel();
|
||||||
} }>Show unverified address</button>
|
showUnverifiedAddress();
|
||||||
</div>
|
} }>Show unverified address</button>
|
||||||
);
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
const enable: string = device.features.passphrase_protection ? 'Enable' : 'Disable';
|
||||||
|
return (
|
||||||
|
<div className="confirm-address-unverified">
|
||||||
|
<button className="close-modal transparent" onClick={ onCancel }></button>
|
||||||
|
<h3>{ device.instanceLabel } is unavailable</h3>
|
||||||
|
<p>To prevent phishing attacks, you should verify the address on your TREZOR first. { enable } passphrase settings to continue with the verification process.</p>
|
||||||
|
<button onClick={ event => {
|
||||||
|
onCancel();
|
||||||
|
showAddress(account.addressPath);
|
||||||
|
} }>Try again</button>
|
||||||
|
<button className="white" onClick={ event => {
|
||||||
|
onCancel();
|
||||||
|
showUnverifiedAddress();
|
||||||
|
} }>Show unverified address</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,11 @@ const RememberDevice = (props: any): any => {
|
|||||||
const { device } = props.modal;
|
const { device } = props.modal;
|
||||||
const { onCancel, onDuplicateDevice } = props.modalActions;
|
const { onCancel, onDuplicateDevice } = props.modalActions;
|
||||||
return (
|
return (
|
||||||
<div className="pin">
|
<div className="duplicate">
|
||||||
<h3>Duplicate { device.label } ?</h3>
|
<h3>Clone { device.instanceLabel }?</h3>
|
||||||
|
<p>This will create new instance of device which can be used with different passphrase</p>
|
||||||
<label>Device label</label>
|
<button onClick={ event => onDuplicateDevice( { ...device, instanceLabel: "TODO: user label from input" } ) }>Create new instance</button>
|
||||||
<input type="text" />
|
<button className="white" onClick={ onCancel }>Cancel</button>
|
||||||
<button onClick={ onCancel }>Cancel</button>
|
|
||||||
<button onClick={ event => onDuplicateDevice( { ...device, instanceLabel: "kokot" } ) }>Duplicate</button>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,10 @@
|
|||||||
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import raf from 'raf';
|
import raf from 'raf';
|
||||||
|
import { findSelectedDevice } from '../../reducers/TrezorConnectReducer';
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
|
deviceLabel: string;
|
||||||
singleInput: boolean;
|
singleInput: boolean;
|
||||||
passphrase: string;
|
passphrase: string;
|
||||||
passphraseRevision: string;
|
passphraseRevision: string;
|
||||||
@ -25,10 +27,20 @@ export default class PinModal extends Component {
|
|||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
// check if this device is already known
|
// check if this device is already known
|
||||||
const isSavedDevice = props.devices.find(d => d.path === props.modal.device.path && d.remember);
|
// const isSavedDevice = props.devices.find(d => d.path === props.modal.device.path && d.remember);
|
||||||
|
const selected = findSelectedDevice(props.connect);
|
||||||
|
let deviceLabel = props.modal.device.label;
|
||||||
|
let singleInput = false;
|
||||||
|
if (selected && selected.path === props.modal.device.path) {
|
||||||
|
deviceLabel = selected.instanceLabel;
|
||||||
|
singleInput = selected.remember;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.warn("-----PASSS", selected)
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
singleInput: isSavedDevice ? true : false,
|
deviceLabel,
|
||||||
|
singleInput,
|
||||||
passphrase: '',
|
passphrase: '',
|
||||||
passphraseRevision: '',
|
passphraseRevision: '',
|
||||||
passphraseFocused: false,
|
passphraseFocused: false,
|
||||||
@ -220,6 +232,7 @@ export default class PinModal extends Component {
|
|||||||
} = this.props.modal;
|
} = this.props.modal;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
deviceLabel,
|
||||||
singleInput,
|
singleInput,
|
||||||
passphrase,
|
passphrase,
|
||||||
passphraseRevision,
|
passphraseRevision,
|
||||||
@ -242,7 +255,7 @@ export default class PinModal extends Component {
|
|||||||
return (
|
return (
|
||||||
<div className="passphrase">
|
<div className="passphrase">
|
||||||
{/* <button className="close-modal transparent" onClick={ event => this.submit(true) }></button> */}
|
{/* <button className="close-modal transparent" onClick={ event => this.submit(true) }></button> */}
|
||||||
<h3>Enter { device.label } passphrase</h3>
|
<h3>Enter { deviceLabel } passphrase</h3>
|
||||||
<p>Note that passphrase is case-sensitive.</p>
|
<p>Note that passphrase is case-sensitive.</p>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<label>Passphrase</label>
|
<label>Passphrase</label>
|
||||||
|
@ -63,11 +63,20 @@ export default class RememberDevice extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render(): any {
|
render(): any {
|
||||||
const { device } = this.props.modal;
|
const { device, instances } = this.props.modal;
|
||||||
const { onForgetDevice, onRememberDevice } = this.props.modalActions;
|
const { onForgetDevice, onRememberDevice } = this.props.modalActions;
|
||||||
|
|
||||||
|
let label = device.label;
|
||||||
|
let devicePlural = false;
|
||||||
|
if (instances && instances.length > 0) {
|
||||||
|
label = instances.map(i => {
|
||||||
|
return (<span>{i.instanceLabel}</span>);
|
||||||
|
})
|
||||||
|
devicePlural = instances.length > 1;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div className="remember">
|
<div className="remember">
|
||||||
<h3>Forget { device.label } ?</h3>
|
<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 device or to remember it, so that it is still visible even while disconnected?</p>
|
||||||
<button onClick={ event => onForgetDevice(device) }>Forget</button>
|
<button onClick={ event => onForgetDevice(device) }>Forget</button>
|
||||||
<button className="white" onClick={ event => onRememberDevice(device) }><span>Remember <Loader size={ 28 } label={ this.state.countdown } /></span></button>
|
<button className="white" onClick={ event => onRememberDevice(device) }><span>Remember <Loader size={ 28 } label={ this.state.countdown } /></span></button>
|
||||||
@ -81,7 +90,7 @@ export const ForgetDevice = (props: any): any => {
|
|||||||
const { onForgetSingleDevice, onCancel } = props.modalActions;
|
const { onForgetSingleDevice, onCancel } = props.modalActions;
|
||||||
return (
|
return (
|
||||||
<div className="remember">
|
<div className="remember">
|
||||||
<h3>Forget { device.label } ?</h3>
|
<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>
|
<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>
|
<button onClick={ event => onForgetSingleDevice(device) }>Forget</button>
|
||||||
<button className="white" onClick={ onCancel }>Don't forget</button>
|
<button className="white" onClick={ onCancel }>Don't forget</button>
|
||||||
@ -94,7 +103,7 @@ export const DisconnectDevice = (props: any): any => {
|
|||||||
const { onForgetSingleDevice, onCancel } = props.modalActions;
|
const { onForgetSingleDevice, onCancel } = props.modalActions;
|
||||||
return (
|
return (
|
||||||
<div className="remember">
|
<div className="remember">
|
||||||
<h3>Unplug { device.label }</h3>
|
<h3>Unplug { device.instanceLabel }</h3>
|
||||||
<p>TREZOR Wallet will forget your TREZOR right after you disconnect it.</p>
|
<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>
|
<b>TODO: its not true, actually i've already forget those data!!!</b>
|
||||||
</div>
|
</div>
|
||||||
|
@ -105,6 +105,7 @@ const mapStateToProps = (state: any, own: any): any => {
|
|||||||
modal: state.modal,
|
modal: state.modal,
|
||||||
accounts: state.accounts,
|
accounts: state.accounts,
|
||||||
devices: state.connect.devices,
|
devices: state.connect.devices,
|
||||||
|
connect: state.connect,
|
||||||
sendForm: state.sendForm,
|
sendForm: state.sendForm,
|
||||||
receive: state.receive,
|
receive: state.receive,
|
||||||
localStorage: state.localStorage
|
localStorage: state.localStorage
|
@ -2,7 +2,10 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { bindActionCreators } from 'redux';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
import { Notification } from '../common/Notification';
|
import { Notification } from '../common/Notification';
|
||||||
|
import * as TrezorConnectActions from '../../actions/TrezorConnectActions';
|
||||||
|
|
||||||
const Acquire = (props: any): any => {
|
const Acquire = (props: any): any => {
|
||||||
|
|
||||||
@ -21,19 +24,24 @@ const Acquire = (props: any): any => {
|
|||||||
title="Device is used in other window"
|
title="Device is used in other window"
|
||||||
message="Do you want to use your device in this window?"
|
message="Do you want to use your device in this window?"
|
||||||
className="info"
|
className="info"
|
||||||
cancelable={false}
|
cancelable={ false }
|
||||||
actions={actions}
|
actions={ actions }
|
||||||
close={ () => {} }
|
close={ () => {} }
|
||||||
/>
|
/>
|
||||||
{/* <div className="warning">
|
|
||||||
<div>
|
|
||||||
<h2></h2>
|
|
||||||
<p></p>
|
|
||||||
</div>
|
|
||||||
<button onClick={ event => props.acquireDevice() }>Acquire device</button>
|
|
||||||
</div> */}
|
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Acquire;
|
const mapStateToProps = (state, own) => {
|
||||||
|
return {
|
||||||
|
connect: state.connect
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => {
|
||||||
|
return {
|
||||||
|
acquireDevice: bindActionCreators(TrezorConnectActions.acquire, dispatch),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(Acquire);
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { bindActionCreators } from 'redux';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
const Bootloader = (props: any): any => {
|
const Bootloader = (props: any): any => {
|
||||||
return (
|
return (
|
||||||
@ -11,4 +13,15 @@ const Bootloader = (props: any): any => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Bootloader;
|
const mapStateToProps = (state, own) => {
|
||||||
|
return {
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => {
|
||||||
|
return {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(Bootloader);
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { bindActionCreators } from 'redux';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
const Dashboard = (props: any): any => {
|
const Dashboard = (props: any): any => {
|
||||||
return (
|
return (
|
||||||
@ -16,4 +18,15 @@ const Dashboard = (props: any): any => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Dashboard;
|
const mapStateToProps = (state, own) => {
|
||||||
|
return {
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => {
|
||||||
|
return {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(Dashboard);
|
||||||
|
27
src/js/components/wallet/DeviceSettings.js
Normal file
27
src/js/components/wallet/DeviceSettings.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/* @flow */
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { bindActionCreators } from 'redux';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
export const DeviceSettings = (props: any): any => {
|
||||||
|
return (
|
||||||
|
<section className="settings">
|
||||||
|
Device settings
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state, own) => {
|
||||||
|
return {
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => {
|
||||||
|
return {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(DeviceSettings);
|
@ -2,18 +2,23 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
import { bindActionCreators } from 'redux';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
import Tooltip from 'rc-tooltip';
|
||||||
import { QRCode } from 'react-qr-svg';
|
import { QRCode } from 'react-qr-svg';
|
||||||
|
|
||||||
import AbstractAccount from './account/AbstractAccount';
|
import AbstractAccount from './account/AbstractAccount';
|
||||||
import { Notification } from '../common/Notification';
|
import { Notification } from '../common/Notification';
|
||||||
import Tooltip from 'rc-tooltip';
|
import * as ReceiveActions from '../../actions/ReceiveActions';
|
||||||
|
|
||||||
export default class Receive extends AbstractAccount {
|
class Receive extends AbstractAccount {
|
||||||
render() {
|
render() {
|
||||||
return super.render(this.props.receive) || _render(this.props);
|
return super.render(this.props.receive) || _render(this.props, this.device, this.account, this.deviceStatusNotification);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const _render = (props: any): any => {
|
const _render = (props: any, device, account, deviceStatusNotification): any => {
|
||||||
|
|
||||||
const {
|
const {
|
||||||
network,
|
network,
|
||||||
@ -23,8 +28,8 @@ const _render = (props: any): any => {
|
|||||||
addressUnverified,
|
addressUnverified,
|
||||||
} = props.receive;
|
} = props.receive;
|
||||||
|
|
||||||
const device = props.devices.find(d => d.state === deviceState);
|
// const device = props.devices.find(d => d.state === deviceState);
|
||||||
const account = props.accounts.find(a => a.deviceState === deviceState && a.index === accountIndex && a.network === network);
|
// const account = props.accounts.find(a => a.deviceState === deviceState && a.index === accountIndex && a.network === network);
|
||||||
|
|
||||||
let qrCode = null;
|
let qrCode = null;
|
||||||
let address = `${account.address.substring(0, 20)}...`;
|
let address = `${account.address.substring(0, 20)}...`;
|
||||||
@ -50,7 +55,7 @@ const _render = (props: any): any => {
|
|||||||
className = addressUnverified ? 'address unverified' : 'address';
|
className = addressUnverified ? 'address unverified' : 'address';
|
||||||
|
|
||||||
const tooltip = addressUnverified ?
|
const tooltip = addressUnverified ?
|
||||||
(<div>Unverified address.<br/>{ device.connected ? 'Show on TREZOR' : 'Connect your TREZOR to verify it.' }</div>)
|
(<div>Unverified address.<br/>{ device.connected && device.available ? 'Show on TREZOR' : 'Connect your TREZOR to verify it.' }</div>)
|
||||||
:
|
:
|
||||||
(<div>{ device.connected ? 'Show on TREZOR' : 'Connect your TREZOR to verify address.' }</div>);
|
(<div>{ device.connected ? 'Show on TREZOR' : 'Connect your TREZOR to verify address.' }</div>);
|
||||||
|
|
||||||
@ -68,9 +73,7 @@ const _render = (props: any): any => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="receive">
|
<section className="receive">
|
||||||
{ !device.connected ? (
|
{ deviceStatusNotification }
|
||||||
<Notification className="info" title={ `Device ${ device.instanceLabel } is disconnected` } />
|
|
||||||
) : null }
|
|
||||||
<h2>Receive Ethereum or tokens</h2>
|
<h2>Receive Ethereum or tokens</h2>
|
||||||
|
|
||||||
<div className={ className }>
|
<div className={ className }>
|
||||||
@ -86,3 +89,23 @@ const _render = (props: any): any => {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state, own) => {
|
||||||
|
return {
|
||||||
|
location: state.router.location,
|
||||||
|
devices: state.connect.devices,
|
||||||
|
accounts: state.accounts,
|
||||||
|
discovery: state.discovery,
|
||||||
|
receive: state.receive
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => {
|
||||||
|
return {
|
||||||
|
initAccount: bindActionCreators(ReceiveActions.init, dispatch),
|
||||||
|
updateAccount: bindActionCreators(ReceiveActions.update, dispatch),
|
||||||
|
disposeAccount: bindActionCreators(ReceiveActions.dispose, dispatch),
|
||||||
|
showAddress: bindActionCreators(ReceiveActions.showAddress, dispatch),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(Receive);
|
@ -1,12 +0,0 @@
|
|||||||
/* @flow */
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default (props: any): any => {
|
|
||||||
return (
|
|
||||||
<section className="settings">
|
|
||||||
Settings
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
}
|
|
@ -2,8 +2,10 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { bindActionCreators } from 'redux';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
export default (props: any): any => {
|
const SignVerify = (props: any): any => {
|
||||||
return (
|
return (
|
||||||
<section className="signverify">
|
<section className="signverify">
|
||||||
<div className="sign">
|
<div className="sign">
|
||||||
@ -27,3 +29,16 @@ export default (props: any): any => {
|
|||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state, own) => {
|
||||||
|
return {
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => {
|
||||||
|
return {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(SignVerify);
|
27
src/js/components/wallet/WalletSettings.js
Normal file
27
src/js/components/wallet/WalletSettings.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/* @flow */
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { bindActionCreators } from 'redux';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
export const WalletSettings = (props: any): any => {
|
||||||
|
return (
|
||||||
|
<section className="settings">
|
||||||
|
Wallet settings
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state, own) => {
|
||||||
|
return {
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => {
|
||||||
|
return {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(WalletSettings);
|
@ -3,19 +3,54 @@
|
|||||||
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Notification } from '../../common/Notification';
|
import { Notification } from '../../common/Notification';
|
||||||
|
import { findDevice } from '../../../utils/reducerUtils';
|
||||||
|
import type { TrezorDevice } from '../../../reducers/TrezorConnectReducer';
|
||||||
|
|
||||||
|
export type AccountState = {
|
||||||
|
device: TrezorDevice;
|
||||||
|
discovery: any;
|
||||||
|
account: any;
|
||||||
|
}
|
||||||
|
|
||||||
export default class AbstractAccount extends Component {
|
export default class AbstractAccount extends Component {
|
||||||
|
|
||||||
|
device: TrezorDevice;
|
||||||
|
discovery: any;
|
||||||
|
account: any;
|
||||||
|
deviceStatusNotification: any;
|
||||||
|
|
||||||
|
constructor(props: any) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setLocalVars(vars: any) {
|
||||||
|
this.device = vars.device;
|
||||||
|
this.discovery = vars.discovery;
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.props.initAccount();
|
this.props.initAccount();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUpdate(newProps: any) {
|
componentWillUpdate(newProps: any) {
|
||||||
|
this.device = null;
|
||||||
|
this.discovery = null;
|
||||||
|
this.account = null;
|
||||||
|
this.deviceStatusNotification = null;
|
||||||
|
|
||||||
this.props.updateAccount();
|
this.props.updateAccount();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.props.disposeAccount();
|
this.props.disposeAccount();
|
||||||
|
|
||||||
|
this.device = null;
|
||||||
|
this.discovery = null;
|
||||||
|
this.account = null;
|
||||||
|
this.deviceStatusNotification = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
render(state: any): any {
|
render(state: any): any {
|
||||||
@ -23,31 +58,49 @@ export default class AbstractAccount extends Component {
|
|||||||
const props = this.props;
|
const props = this.props;
|
||||||
|
|
||||||
if (!state.deviceState) {
|
if (!state.deviceState) {
|
||||||
return (<section></section>);
|
return (<section><Notification className="info" title="Loading device" /></section>);
|
||||||
}
|
}
|
||||||
|
|
||||||
const device = this.props.devices.find(d => d.state === state.deviceState);
|
const device = findDevice(this.props.devices, state.deviceState, state.deviceId, state.deviceInstance);
|
||||||
|
|
||||||
if (!device) {
|
if (!device) {
|
||||||
return (<section>Device with state {state.deviceState} not found</section>);
|
return (<section>Device with state {state.deviceState} not found</section>);
|
||||||
}
|
}
|
||||||
const discovery = props.discovery.find(d => d.deviceState === device.state && d.network === state.network);
|
const discovery = props.discovery.find(d => d.deviceState === device.state && d.network === state.network);
|
||||||
const account = props.accounts.find(a => a.deviceState === state.deviceState && a.index === state.accountIndex && a.network === state.network);
|
const account = props.accounts.find(a => a.deviceState === state.deviceState && a.index === state.accountIndex && a.network === state.network);
|
||||||
|
let deviceStatusNotification = null;
|
||||||
|
|
||||||
if (!account) {
|
if (!account) {
|
||||||
if (!discovery || discovery.waitingForDevice) {
|
if (!discovery || discovery.waitingForDevice) {
|
||||||
return (
|
if (device.connected) {
|
||||||
<section>
|
if (device.available) {
|
||||||
<Notification
|
return (
|
||||||
className="info"
|
<section>
|
||||||
title="Loading account"
|
<Notification className="info" title="Loading account" />
|
||||||
message=""
|
</section>
|
||||||
/>
|
);
|
||||||
</section>
|
} else {
|
||||||
);
|
return (
|
||||||
|
<section>
|
||||||
|
<Notification
|
||||||
|
className="info"
|
||||||
|
title={ `Device ${ device.instanceLabel } is unavailable` }
|
||||||
|
message="Change passphrase settings to use this device"
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<section>
|
||||||
|
<Notification className="info" title={ `Device ${ device.instanceLabel } is disconnected` } />
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
} else if (discovery.completed) {
|
} else if (discovery.completed) {
|
||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
<Notification className="warning" title="Account is not exist" />
|
<Notification className="warning" title="Account does not exist" />
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -57,8 +110,20 @@ export default class AbstractAccount extends Component {
|
|||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (!device.connected) {
|
||||||
|
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" />;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set class variables for extender classes
|
||||||
|
this.device = device;
|
||||||
|
this.discovery = discovery;
|
||||||
|
this.account = account;
|
||||||
|
this.deviceStatusNotification = deviceStatusNotification;
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -17,8 +17,9 @@ const AccountSelection = (props: any): any => {
|
|||||||
if (!selected) return null;
|
if (!selected) return null;
|
||||||
|
|
||||||
const { location } = props.router;
|
const { location } = props.router;
|
||||||
|
const urlParams = location.params;
|
||||||
const accounts = props.accounts;
|
const accounts = props.accounts;
|
||||||
const baseUrl: string = `/device/${location.params.device}`;
|
const baseUrl: string = urlParams.deviceInstance ? `/device/${urlParams.device}:${urlParams.deviceInstance}` : `/device/${urlParams.device}`;
|
||||||
|
|
||||||
const { config } = props.localStorage;
|
const { config } = props.localStorage;
|
||||||
const selectedCoin = config.coins.find(c => c.network === location.params.network);
|
const selectedCoin = config.coins.find(c => c.network === location.params.network);
|
||||||
|
@ -48,7 +48,7 @@ const Aside = (props: any): any => {
|
|||||||
// );
|
// );
|
||||||
// }
|
// }
|
||||||
|
|
||||||
let menu = null;
|
let menu = <section></section>;
|
||||||
|
|
||||||
if (props.deviceDropdownOpened) {
|
if (props.deviceDropdownOpened) {
|
||||||
menu = <DeviceDropdown {...props} />;
|
menu = <DeviceDropdown {...props} />;
|
||||||
@ -77,4 +77,4 @@ const Aside = (props: any): any => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Aside;
|
export default Aside;
|
||||||
|
@ -34,6 +34,10 @@ const Value = (props: any): any => {
|
|||||||
|
|
||||||
const deviceMenuItems: Array<any> = [];
|
const deviceMenuItems: Array<any> = [];
|
||||||
|
|
||||||
|
if (device.features && device.features.passphrase_protection) {
|
||||||
|
deviceMenuItems.push("settings"); // TODO: clone
|
||||||
|
}
|
||||||
|
|
||||||
if (device.unacquired) {
|
if (device.unacquired) {
|
||||||
css += " unacquired";
|
css += " unacquired";
|
||||||
deviceStatus = "Used in other window";
|
deviceStatus = "Used in other window";
|
||||||
@ -49,6 +53,9 @@ const Value = (props: any): any => {
|
|||||||
if (!device.connected) {
|
if (!device.connected) {
|
||||||
css += " reload-features";
|
css += " reload-features";
|
||||||
deviceStatus = "Disconnected";
|
deviceStatus = "Disconnected";
|
||||||
|
} else if (!device.available) {
|
||||||
|
css += " unavailable";
|
||||||
|
deviceStatus = "Unavailable";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device.remember) {
|
if (device.remember) {
|
||||||
@ -59,6 +66,8 @@ const Value = (props: any): any => {
|
|||||||
css += " trezor-t";
|
css += " trezor-t";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const deviceMenuButtons = deviceMenuItems.map((item, index) => {
|
const deviceMenuButtons = deviceMenuItems.map((item, index) => {
|
||||||
return (
|
return (
|
||||||
<div key={ item } className={ item } onClick={ event => onClick(event, item, device) }></div>
|
<div key={ item } className={ item } onClick={ event => onClick(event, item, device) }></div>
|
||||||
@ -81,9 +90,6 @@ const Value = (props: any): any => {
|
|||||||
<span className="label">{ device.instanceLabel }</span>
|
<span className="label">{ device.instanceLabel }</span>
|
||||||
<span className="status">{ deviceStatus }</span>
|
<span className="status">{ deviceStatus }</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="device-menu">
|
|
||||||
{ deviceMenuButtons }
|
|
||||||
</div>
|
|
||||||
<div className="arrow">
|
<div className="arrow">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -143,8 +149,7 @@ export const DeviceSelect = (props: any): any => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("DEVSEL", props)
|
const disabled: boolean = (devices.length < 1 && transport && transport.version.indexOf('webusb') < 0);
|
||||||
const disabled: boolean = (devices && devices.length <= 1 && transport && transport.type.indexOf('webusb') < 0);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Value
|
<Value
|
||||||
@ -169,17 +174,16 @@ export class DeviceDropdown extends Component {
|
|||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
const transport: any = this.props.connect.transport;
|
const transport: any = this.props.connect.transport;
|
||||||
if (transport && transport.type.indexOf('webusb') >= 0)
|
if (transport && transport.version.indexOf('webusb') >= 0)
|
||||||
TrezorConnect.renderWebUSBButton();
|
TrezorConnect.renderWebUSBButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
mouseDownHandler(event: MouseEvent): void {
|
mouseDownHandler(event: MouseEvent): void {
|
||||||
console.log("HANDLE DOWN!!!!", event)
|
|
||||||
let elem = event.target;
|
let elem = event.target;
|
||||||
let block: boolean = false;
|
let block: boolean = false;
|
||||||
while (elem.parentElement) {
|
while (elem.parentElement) {
|
||||||
// if (elem.className.indexOf('aside-button') >= 0) {
|
// if (elem.className.indexOf('aside-button') >= 0) {
|
||||||
if (elem.tagName.toLowerCase() === 'aside') {
|
if (elem.tagName.toLowerCase() === 'aside' || (elem.className && elem.className.indexOf('modal-container') >= 0)) {
|
||||||
block = true;
|
block = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -199,7 +203,7 @@ export class DeviceDropdown extends Component {
|
|||||||
window.addEventListener('mousedown', this.mouseDownHandler, false);
|
window.addEventListener('mousedown', this.mouseDownHandler, false);
|
||||||
// window.addEventListener('blur', this.blurHandler, false);
|
// window.addEventListener('blur', this.blurHandler, false);
|
||||||
const transport: any = this.props.connect.transport;
|
const transport: any = this.props.connect.transport;
|
||||||
if (transport && transport.type.indexOf('webusb') >= 0)
|
if (transport && transport.version.indexOf('webusb') >= 0)
|
||||||
TrezorConnect.renderWebUSBButton();
|
TrezorConnect.renderWebUSBButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,16 +212,69 @@ export class DeviceDropdown extends Component {
|
|||||||
// window.removeEventListener('blur', this.blurHandler, false);
|
// window.removeEventListener('blur', this.blurHandler, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onDeviceMenuClick(item, device): void {
|
||||||
|
if (item.type === 'reload') {
|
||||||
|
this.props.acquireDevice(device);
|
||||||
|
} else if (item.type === 'forget') {
|
||||||
|
// this.props.toggleDeviceDropdown(false);
|
||||||
|
this.props.forgetDevice(device);
|
||||||
|
} else if (item.type === 'clone') {
|
||||||
|
this.props.duplicateDevice(device);
|
||||||
|
} else if (item.type === 'settings') {
|
||||||
|
this.props.toggleDeviceDropdown(false);
|
||||||
|
this.props.gotoDeviceSettings(device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
||||||
const { devices, transport } = this.props.connect;
|
const { devices, transport } = this.props.connect;
|
||||||
const selected = findSelectedDevice(this.props.connect);
|
const selected = findSelectedDevice(this.props.connect);
|
||||||
|
|
||||||
let webUsbButton = null;
|
let webUsbButton = null;
|
||||||
if (transport && transport.type.indexOf('webusb') >= 0) {
|
if (transport && transport.version.indexOf('webusb') >= 0) {
|
||||||
webUsbButton = <button className="trezor-webusb-button">Check for devices</button>;
|
webUsbButton = <button className="trezor-webusb-button">Check for devices</button>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let currentDeviceMenu = null;
|
||||||
|
if (selected.features) {
|
||||||
|
const deviceMenuItems: Array<any> = [];
|
||||||
|
|
||||||
|
if (selected.isUsedElsewhere) {
|
||||||
|
deviceMenuItems.push({ type: "reload", label: "Renew session" });
|
||||||
|
} else if (selected.featuresNeedsReload) {
|
||||||
|
deviceMenuItems.push({ type: "reload", label: "Reload device" });
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceMenuItems.push({ type: "settings", label: "Device settings" });
|
||||||
|
if (selected.features.passphrase_protection && selected.connected && selected.available) {
|
||||||
|
deviceMenuItems.push({ type: "clone", label: "Clone device" });
|
||||||
|
}
|
||||||
|
if (selected.remember) {
|
||||||
|
deviceMenuItems.push({ type: "forget", label: "Forget device" });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const deviceMenuButtons = deviceMenuItems.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<div key={ item.type } className={ item.type } onClick={ event => this.onDeviceMenuClick(item, selected) }>{ item.label}</div>
|
||||||
|
)
|
||||||
|
});
|
||||||
|
currentDeviceMenu = deviceMenuButtons.length < 1 ? null : (
|
||||||
|
<div className="device-menu">
|
||||||
|
{ deviceMenuButtons }
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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) => {
|
const deviceList: Array<any> = devices.map((dev, index) => {
|
||||||
if (dev === selected) return null;
|
if (dev === selected) return null;
|
||||||
|
|
||||||
@ -227,6 +284,8 @@ export class DeviceDropdown extends Component {
|
|||||||
deviceStatus = "Used in other window";
|
deviceStatus = "Used in other window";
|
||||||
} else if (!dev.connected) {
|
} else if (!dev.connected) {
|
||||||
deviceStatus = "Disconnected";
|
deviceStatus = "Disconnected";
|
||||||
|
} else if (!dev.available) {
|
||||||
|
deviceStatus = "Unavailable";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev.features && dev.features.major_version > 1) {
|
if (dev.features && dev.features.major_version > 1) {
|
||||||
@ -245,6 +304,7 @@ export class DeviceDropdown extends Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
|
{ currentDeviceMenu }
|
||||||
{ webUsbButton }
|
{ webUsbButton }
|
||||||
{ deviceList }
|
{ deviceList }
|
||||||
</section>
|
</section>
|
||||||
|
@ -5,23 +5,25 @@ import React, { Component, PropTypes } from 'react';
|
|||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
import Aside from '../components/wallet/aside/Aside';
|
|
||||||
import * as TrezorConnectActions from '../actions/TrezorConnectActions';
|
|
||||||
import { toggleDeviceDropdown } from '../actions/AppActions';
|
|
||||||
|
|
||||||
function mapStateToProps(state, own) {
|
import * as TrezorConnectActions from '../../../actions/TrezorConnectActions';
|
||||||
|
import { toggleDeviceDropdown } from '../../../actions/WalletActions';
|
||||||
|
|
||||||
|
import Aside from './Aside';
|
||||||
|
|
||||||
|
const mapStateToProps = (state, own) => {
|
||||||
return {
|
return {
|
||||||
connect: state.connect,
|
connect: state.connect,
|
||||||
accounts: state.accounts,
|
accounts: state.accounts,
|
||||||
router: state.router,
|
router: state.router,
|
||||||
deviceDropdownOpened: state.DOM.deviceDropdownOpened,
|
deviceDropdownOpened: state.wallet.dropdownOpened,
|
||||||
fiat: state.fiat,
|
fiat: state.fiat,
|
||||||
localStorage: state.localStorage,
|
localStorage: state.localStorage,
|
||||||
discovery: state.discovery
|
discovery: state.discovery
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
return {
|
return {
|
||||||
//onAccountSelect: bindActionCreators(AccountActions.onAccountSelect, dispatch),
|
//onAccountSelect: bindActionCreators(AccountActions.onAccountSelect, dispatch),
|
||||||
toggleDeviceDropdown: bindActionCreators(toggleDeviceDropdown, dispatch),
|
toggleDeviceDropdown: bindActionCreators(toggleDeviceDropdown, dispatch),
|
||||||
@ -29,6 +31,7 @@ function mapDispatchToProps(dispatch) {
|
|||||||
acquireDevice: bindActionCreators(TrezorConnectActions.acquire, dispatch),
|
acquireDevice: bindActionCreators(TrezorConnectActions.acquire, dispatch),
|
||||||
forgetDevice: bindActionCreators(TrezorConnectActions.forget, dispatch),
|
forgetDevice: bindActionCreators(TrezorConnectActions.forget, dispatch),
|
||||||
duplicateDevice: bindActionCreators(TrezorConnectActions.duplicateDevice, dispatch),
|
duplicateDevice: bindActionCreators(TrezorConnectActions.duplicateDevice, dispatch),
|
||||||
|
gotoDeviceSettings: bindActionCreators(TrezorConnectActions.gotoDeviceSettings, dispatch),
|
||||||
onSelectDevice: bindActionCreators(TrezorConnectActions.onSelectDevice, dispatch),
|
onSelectDevice: bindActionCreators(TrezorConnectActions.onSelectDevice, dispatch),
|
||||||
};
|
};
|
||||||
}
|
}
|
58
src/js/components/wallet/index.js
Normal file
58
src/js/components/wallet/index.js
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/* @flow */
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { bindActionCreators } from 'redux';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { Route, withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
|
import Header from '../common/Header';
|
||||||
|
import Footer from '../common/Footer';
|
||||||
|
import AccountTabs from './account/AccountTabs';
|
||||||
|
import AsideContainer from './aside';
|
||||||
|
import ModalContainer from '../modal';
|
||||||
|
import Notifications from '../common/Notification';
|
||||||
|
import Log from '../common/Log';
|
||||||
|
|
||||||
|
const Content = (props) => {
|
||||||
|
return (
|
||||||
|
<article>
|
||||||
|
<nav>
|
||||||
|
<Route path="/device/:device/network/:network/address/:address" component={ AccountTabs } />
|
||||||
|
</nav>
|
||||||
|
<Notifications />
|
||||||
|
<Log />
|
||||||
|
{ props.children }
|
||||||
|
<Footer />
|
||||||
|
</article>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Wallet = (props: any): any => {
|
||||||
|
return (
|
||||||
|
<div className="app">
|
||||||
|
<Header />
|
||||||
|
<main>
|
||||||
|
<AsideContainer />
|
||||||
|
<Content>
|
||||||
|
{ props.children }
|
||||||
|
</Content>
|
||||||
|
</main>
|
||||||
|
<ModalContainer />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state, own) => {
|
||||||
|
return {
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => {
|
||||||
|
return { };
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withRouter(
|
||||||
|
connect(mapStateToProps, mapDispatchToProps)(Wallet)
|
||||||
|
);
|
@ -11,16 +11,16 @@ import AbstractAccount from '../account/AbstractAccount';
|
|||||||
|
|
||||||
export default class Send extends AbstractAccount {
|
export default class Send extends AbstractAccount {
|
||||||
render() {
|
render() {
|
||||||
return super.render(this.props.sendForm) || _render(this.props);
|
return super.render(this.props.sendForm) || _render(this.props, this.device, this.discovery, this.account, this.deviceStatusNotification);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const _render = (props: any): any => {
|
const _render = (props: any, device, discovery, account, deviceStatusNotification): any => {
|
||||||
|
|
||||||
const device = props.devices.find(device => device.state === props.sendForm.deviceState);
|
// const device = props.devices.find(device => device.state === props.sendForm.deviceState);
|
||||||
const discovery = props.discovery.find(d => d.deviceState === device.state && d.network === props.sendForm.network);
|
// const discovery = props.discovery.find(d => d.deviceState === device.state && d.network === props.sendForm.network);
|
||||||
const account = props.accounts.find(a => a.deviceState === props.sendForm.deviceState && a.index === props.sendForm.accountIndex && a.network === props.sendForm.network);
|
// const account = props.accounts.find(a => a.deviceState === props.sendForm.deviceState && a.index === props.sendForm.accountIndex && a.network === props.sendForm.network);
|
||||||
const addressTokens = props.tokens.filter(t => t.ethAddress === account.address);
|
const addressTokens = props.tokens.filter(t => t.ethAddress === account.address);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -87,9 +87,16 @@ const _render = (props: any): any => {
|
|||||||
buttonLabel += ` ${total} ${ selectedCoin.symbol }`;
|
buttonLabel += ` ${total} ${ selectedCoin.symbol }`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device && !device.connected) {
|
if (device) {
|
||||||
buttonLabel = 'Device is not connected';
|
|
||||||
buttonDisabled = true;
|
if (!device.connected){
|
||||||
|
buttonLabel = 'Device is not connected';
|
||||||
|
buttonDisabled = true;
|
||||||
|
} else if (!device.available) {
|
||||||
|
buttonLabel = 'Device is unavailable';
|
||||||
|
buttonDisabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let notification = null;
|
let notification = null;
|
||||||
@ -97,9 +104,7 @@ const _render = (props: any): any => {
|
|||||||
return (
|
return (
|
||||||
<section className="send-form">
|
<section className="send-form">
|
||||||
|
|
||||||
{ !device.connected ? (
|
{ deviceStatusNotification }
|
||||||
<Notification className="info" title={ `Device ${ device.instanceLabel } is disconnected` } />
|
|
||||||
) : null }
|
|
||||||
|
|
||||||
<h2>Send Ethereum or tokens</h2>
|
<h2>Send Ethereum or tokens</h2>
|
||||||
<div className="row address-input">
|
<div className="row address-input">
|
||||||
|
@ -5,10 +5,10 @@ import React, { Component, PropTypes } from 'react';
|
|||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import SendForm from '../components/wallet/send/SendForm';
|
import * as SendFormActions from '../../../actions/SendFormActions';
|
||||||
import * as SendFormActions from '../actions/SendFormActions';
|
import SendForm from './SendForm';
|
||||||
|
|
||||||
function mapStateToProps(state, own) {
|
const mapStateToProps = (state, own) => {
|
||||||
return {
|
return {
|
||||||
location: state.router.location,
|
location: state.router.location,
|
||||||
devices: state.connect.devices,
|
devices: state.connect.devices,
|
||||||
@ -22,13 +22,13 @@ function mapStateToProps(state, own) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
return {
|
return {
|
||||||
sendFormActions: bindActionCreators(SendFormActions, dispatch),
|
sendFormActions: bindActionCreators(SendFormActions, dispatch),
|
||||||
initAccount: bindActionCreators(SendFormActions.init, dispatch),
|
initAccount: bindActionCreators(SendFormActions.init, dispatch),
|
||||||
updateAccount: bindActionCreators(SendFormActions.update, dispatch),
|
updateAccount: bindActionCreators(SendFormActions.update, dispatch),
|
||||||
disposeAccount: bindActionCreators(SendFormActions.dispose, dispatch),
|
disposeAccount: bindActionCreators(SendFormActions.dispose, dispatch),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(SendForm);
|
export default connect(mapStateToProps, mapDispatchToProps)(SendForm)
|
@ -9,27 +9,28 @@ import AbstractAccount from '../account/AbstractAccount';
|
|||||||
import { Notification } from '../../common/Notification';
|
import { Notification } from '../../common/Notification';
|
||||||
import SummaryDetails from './SummaryDetails.js';
|
import SummaryDetails from './SummaryDetails.js';
|
||||||
import SummaryTokens from './SummaryTokens.js';
|
import SummaryTokens from './SummaryTokens.js';
|
||||||
|
import { findDevice } from '../../../utils/reducerUtils';
|
||||||
|
|
||||||
|
|
||||||
export default class Summary extends AbstractAccount {
|
export default class Summary extends AbstractAccount {
|
||||||
render() {
|
render() {
|
||||||
return super.render(this.props.summary) || _render(this.props);
|
console.warn("RENDER SUMMARY!", this.device, this.discovery, this)
|
||||||
|
return super.render(this.props.summary) || _render(this.props, this.device, this.discovery, this.account, this.deviceStatusNotification);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const _render = (props: any): any => {
|
const _render = (props: any, device, discovery, account, deviceStatusNotification): any => {
|
||||||
|
|
||||||
const device = props.devices.find(d => d.state === props.summary.deviceState);
|
//const device = props.devices.find(d => d.state === props.summary.deviceState && d.features.device_id === props.summary.deviceId);
|
||||||
const discovery = props.discovery.find(d => d.deviceState === device.state && d.network === props.summary.network);
|
// const device = findDevice(props.devices, props.summary.deviceState, props.summary.deviceId);
|
||||||
const account = props.accounts.find(a => a.deviceState === props.summary.deviceState && a.index === props.summary.accountIndex && a.network === props.summary.network);
|
// const discovery = props.discovery.find(d => d.deviceState === device.state && d.network === props.summary.network);
|
||||||
|
//const account = props.accounts.find(a => a.deviceState === props.summary.deviceState && a.index === props.summary.accountIndex && a.network === props.summary.network);
|
||||||
const tokens = props.tokens.filter(t => t.ethAddress === account.address);
|
const tokens = props.tokens.filter(t => t.ethAddress === account.address);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
<section className="summary">
|
<section className="summary">
|
||||||
{ !device.connected ? (
|
{ deviceStatusNotification }
|
||||||
<Notification className="info" title={ `Device ${ device.instanceLabel } is disconnected` } />
|
|
||||||
) : null }
|
|
||||||
|
|
||||||
<h2 className={ `summary-header ${props.summary.network}` }>Address #{ parseInt(props.match.params.address) + 1 }</h2>
|
<h2 className={ `summary-header ${props.summary.network}` }>Address #{ parseInt(props.match.params.address) + 1 }</h2>
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import { connect } from 'react-redux';
|
|||||||
import Summary from './Summary';
|
import Summary from './Summary';
|
||||||
import * as SummaryActions from '../../../actions/SummaryActions';
|
import * as SummaryActions from '../../../actions/SummaryActions';
|
||||||
|
|
||||||
function mapStateToProps(state, own) {
|
const mapStateToProps = (state, own) => {
|
||||||
return {
|
return {
|
||||||
location: state.router.location,
|
location: state.router.location,
|
||||||
devices: state.connect.devices,
|
devices: state.connect.devices,
|
||||||
@ -21,7 +21,7 @@ function mapStateToProps(state, own) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
return {
|
return {
|
||||||
summaryActions: bindActionCreators(SummaryActions, dispatch),
|
summaryActions: bindActionCreators(SummaryActions, dispatch),
|
||||||
initAccount: bindActionCreators(SummaryActions.init, dispatch),
|
initAccount: bindActionCreators(SummaryActions.init, dispatch),
|
@ -1,23 +0,0 @@
|
|||||||
/* @flow */
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
|
|
||||||
import Acquire from '../components/wallet/Acquire';
|
|
||||||
import * as TrezorConnectActions from '../actions/TrezorConnectActions';
|
|
||||||
|
|
||||||
function mapStateToProps(state, own) {
|
|
||||||
return {
|
|
||||||
connect: state.connect
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
|
||||||
return {
|
|
||||||
acquireDevice: bindActionCreators(TrezorConnectActions.acquire, dispatch),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(Acquire);
|
|
@ -1,21 +0,0 @@
|
|||||||
/* @flow */
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
|
|
||||||
import Bootloader from '../components/wallet/Bootloader';
|
|
||||||
|
|
||||||
function mapStateToProps(state, own) {
|
|
||||||
return {
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
|
||||||
return {
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(Bootloader);
|
|
@ -1,46 +0,0 @@
|
|||||||
/* @flow */
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import { Route } from 'react-router-dom';
|
|
||||||
|
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { withRouter } from 'react-router-dom';
|
|
||||||
import Log from '../components/common/Log';
|
|
||||||
import Notifications from '../components/common/Notification';
|
|
||||||
import Footer from '../components/common/Footer';
|
|
||||||
import AccountTabs from '../components/wallet/account/AccountTabs';
|
|
||||||
|
|
||||||
import * as TrezorConnectActions from '../actions/TrezorConnectActions';
|
|
||||||
import * as LogActions from '../actions/LogActions';
|
|
||||||
|
|
||||||
const Article = (props) => {
|
|
||||||
return (
|
|
||||||
<article>
|
|
||||||
<nav>
|
|
||||||
<Route path="/device/:device/network/:network/address/:address" component={ AccountTabs } />
|
|
||||||
</nav>
|
|
||||||
<Notifications />
|
|
||||||
<Log />
|
|
||||||
{ props.children }
|
|
||||||
<Footer />
|
|
||||||
</article>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapStateToProps(state, own) {
|
|
||||||
return {
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
|
||||||
return {
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default withRouter(
|
|
||||||
connect(mapStateToProps, mapDispatchToProps)(Article)
|
|
||||||
);
|
|
@ -1,21 +0,0 @@
|
|||||||
/* @flow */
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
|
|
||||||
import Dashboard from '../components/wallet/Dashboard';
|
|
||||||
|
|
||||||
function mapStateToProps(state, own) {
|
|
||||||
return {
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
|
||||||
return {
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(Dashboard);
|
|
@ -1,23 +0,0 @@
|
|||||||
/* @flow */
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
|
|
||||||
import History from '../components/wallet/History';
|
|
||||||
import * as SendFormActions from '../actions/SendFormActions';
|
|
||||||
|
|
||||||
function mapStateToProps(state, own) {
|
|
||||||
return {
|
|
||||||
web3: state.web3.web3,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
|
||||||
return {
|
|
||||||
//sendFormActions: bindActionCreators(SendFormActions, dispatch),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(History);
|
|
@ -1,31 +0,0 @@
|
|||||||
/* @flow */
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
|
|
||||||
import Receive from '../components/wallet/Receive';
|
|
||||||
import * as ReceiveActions from '../actions/ReceiveActions';
|
|
||||||
import { getAddress } from '../actions/TrezorConnectActions';
|
|
||||||
|
|
||||||
function mapStateToProps(state, own) {
|
|
||||||
return {
|
|
||||||
location: state.router.location,
|
|
||||||
devices: state.connect.devices,
|
|
||||||
accounts: state.accounts,
|
|
||||||
discovery: state.discovery,
|
|
||||||
receive: state.receive
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
|
||||||
return {
|
|
||||||
initAccount: bindActionCreators(ReceiveActions.init, dispatch),
|
|
||||||
updateAccount: bindActionCreators(ReceiveActions.update, dispatch),
|
|
||||||
disposeAccount: bindActionCreators(ReceiveActions.dispose, dispatch),
|
|
||||||
showAddress: bindActionCreators(ReceiveActions.showAddress, dispatch),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(Receive);
|
|
@ -1,20 +0,0 @@
|
|||||||
/* @flow */
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
|
|
||||||
import Settings from '../components/wallet/Settings';
|
|
||||||
|
|
||||||
function mapStateToProps(state, own) {
|
|
||||||
return {
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
|
||||||
return {
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(Settings);
|
|
@ -1,20 +0,0 @@
|
|||||||
/* @flow */
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
|
|
||||||
import SignVerify from '../components/wallet/SignVerify';
|
|
||||||
|
|
||||||
function mapStateToProps(state, own) {
|
|
||||||
return {
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
|
||||||
return {
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(SignVerify);
|
|
@ -1,31 +0,0 @@
|
|||||||
/* @flow */
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { withRouter } from 'react-router-dom';
|
|
||||||
|
|
||||||
import TopNavigation from '../components/TopNavigation';
|
|
||||||
import * as TrezorConnectActions from '../actions/TrezorConnectActions';
|
|
||||||
import { resizeAppContainer, toggleDeviceDropdown } from '../actions/AppActions';
|
|
||||||
|
|
||||||
function mapStateToProps(state, own) {
|
|
||||||
return {
|
|
||||||
connect: state.connect
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
|
||||||
return {
|
|
||||||
toggleDeviceDropdown: bindActionCreators(toggleDeviceDropdown, dispatch),
|
|
||||||
resizeAppContainer: bindActionCreators(resizeAppContainer, dispatch),
|
|
||||||
acquireDevice: bindActionCreators(TrezorConnectActions.acquire, dispatch),
|
|
||||||
onSelectDevice: bindActionCreators(TrezorConnectActions.onSelectDevice, dispatch),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// export default connect(mapStateToProps, mapDispatchToProps)(TopNavigation);
|
|
||||||
export default withRouter(
|
|
||||||
connect(mapStateToProps, mapDispatchToProps)(TopNavigation)
|
|
||||||
);
|
|
@ -1,40 +0,0 @@
|
|||||||
/* @flow */
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { withRouter } from 'react-router-dom';
|
|
||||||
|
|
||||||
import Header from '../components/common/Header';
|
|
||||||
import AsideContainer from './AsideContainer';
|
|
||||||
import ContentContainer from './ContentContainer';
|
|
||||||
import ModalContainer from '../components/modal/ModalContainer';
|
|
||||||
|
|
||||||
const Wallet = (props: any): any => {
|
|
||||||
return (
|
|
||||||
<div className="app">
|
|
||||||
<Header />
|
|
||||||
<main>
|
|
||||||
<AsideContainer />
|
|
||||||
<ContentContainer>
|
|
||||||
{ props.children }
|
|
||||||
</ContentContainer>
|
|
||||||
</main>
|
|
||||||
<ModalContainer />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapStateToProps(state, own) {
|
|
||||||
return {
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
|
||||||
return { };
|
|
||||||
}
|
|
||||||
|
|
||||||
export default withRouter(
|
|
||||||
connect(mapStateToProps, mapDispatchToProps)(Wallet)
|
|
||||||
);
|
|
@ -1,19 +0,0 @@
|
|||||||
/* @flow */
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
// wrapper layouts
|
|
||||||
export { default as LandingPageContainer } from './LandingPageContainer';
|
|
||||||
export { default as WalletContainer } from './WalletContainer';
|
|
||||||
|
|
||||||
// wallet sections
|
|
||||||
export { default as AcquireContainer } from './AcquireContainer';
|
|
||||||
export { default as BootloaderContainer } from './BootloaderContainer';
|
|
||||||
|
|
||||||
export { default as DashboardContainer } from './DashboardContainer';
|
|
||||||
export { default as HistoryContainer } from './HistoryContainer';
|
|
||||||
export { default as SendFormContainer } from './SendFormContainer';
|
|
||||||
export { default as ReceiveContainer } from './ReceiveContainer';
|
|
||||||
export { default as SignVerifyContainer } from './SignVerifyContainer';
|
|
||||||
|
|
||||||
|
|
||||||
export { default as SettingsContainer } from './SettingsContainer';
|
|
@ -5,7 +5,7 @@ import React from 'react';
|
|||||||
import { render } from 'react-dom';
|
import { render } from 'react-dom';
|
||||||
import store from './store';
|
import store from './store';
|
||||||
import router from './router';
|
import router from './router';
|
||||||
import { onResize, onBeforeUnload } from './actions/AppActions';
|
import { onBeforeUnload } from './actions/WalletActions';
|
||||||
|
|
||||||
import Raven from 'raven-js';
|
import Raven from 'raven-js';
|
||||||
|
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
/* @flow */
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import { ON_RESIZE, TOGGLE_DEVICE_DROPDOWN, RESIZE_CONTAINER } from '../actions/AppActions';
|
|
||||||
import * as WEB3 from '../actions/constants/Web3';
|
|
||||||
|
|
||||||
const WIDTH: number = 1080;
|
|
||||||
const HEIGHT: number = 1920;
|
|
||||||
|
|
||||||
const initialState: Object = {
|
|
||||||
orginalWidth: WIDTH,
|
|
||||||
orginalHeight: HEIGHT,
|
|
||||||
width: window.innerWidth,
|
|
||||||
height: window.innerHeight,
|
|
||||||
scale: Math.min(window.innerWidth / WIDTH, window.innerHeight / HEIGHT),
|
|
||||||
coinDropdownOpened: false,
|
|
||||||
deviceDropdownOpened: false,
|
|
||||||
initialized: false,
|
|
||||||
landingPage: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function DOM(state: Object = initialState, action: Object): any {
|
|
||||||
switch(action.type) {
|
|
||||||
case ON_RESIZE :
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
scale: Math.min(window.innerWidth / WIDTH, window.innerHeight / HEIGHT),
|
|
||||||
}
|
|
||||||
case RESIZE_CONTAINER :
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
coinDropdownOpened: action.opened
|
|
||||||
}
|
|
||||||
case TOGGLE_DEVICE_DROPDOWN :
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
deviceDropdownOpened: action.opened
|
|
||||||
}
|
|
||||||
|
|
||||||
case WEB3.READY :
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
initialized: true
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,7 +2,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { UI, DEVICE } from 'trezor-connect';
|
import { UI, DEVICE } from 'trezor-connect';
|
||||||
import * as ACTIONS from '../actions';
|
|
||||||
import * as RECEIVE from '../actions/constants/receive';
|
import * as RECEIVE from '../actions/constants/receive';
|
||||||
import * as MODAL from '../actions/constants/Modal';
|
import * as MODAL from '../actions/constants/Modal';
|
||||||
import * as CONNECT from '../actions/constants/TrezorConnect';
|
import * as CONNECT from '../actions/constants/TrezorConnect';
|
||||||
@ -10,12 +9,14 @@ import * as CONNECT from '../actions/constants/TrezorConnect';
|
|||||||
type ModalState = {
|
type ModalState = {
|
||||||
opened: boolean;
|
opened: boolean;
|
||||||
device: any;
|
device: any;
|
||||||
|
instances: Array<any>;
|
||||||
windowType: ?string;
|
windowType: ?string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState: ModalState = {
|
const initialState: ModalState = {
|
||||||
opened: false,
|
opened: false,
|
||||||
device: null,
|
device: null,
|
||||||
|
instances: null,
|
||||||
windowType: null
|
windowType: null
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -26,6 +27,7 @@ export default function modal(state: ModalState = initialState, action: any): an
|
|||||||
case RECEIVE.REQUEST_UNVERIFIED :
|
case RECEIVE.REQUEST_UNVERIFIED :
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
device: action.device,
|
||||||
opened: true,
|
opened: true,
|
||||||
windowType: action.type
|
windowType: action.type
|
||||||
}
|
}
|
||||||
@ -36,6 +38,7 @@ export default function modal(state: ModalState = initialState, action: any): an
|
|||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
device: action.device,
|
device: action.device,
|
||||||
|
instances: action.instances,
|
||||||
opened: true,
|
opened: true,
|
||||||
windowType: action.type
|
windowType: action.type
|
||||||
};
|
};
|
||||||
@ -92,7 +95,7 @@ export default function modal(state: ModalState = initialState, action: any): an
|
|||||||
}
|
}
|
||||||
|
|
||||||
case UI.CLOSE_UI_WINDOW :
|
case UI.CLOSE_UI_WINDOW :
|
||||||
case ACTIONS.CLOSE_MODAL :
|
case MODAL.CLOSE :
|
||||||
|
|
||||||
case CONNECT.FORGET :
|
case CONNECT.FORGET :
|
||||||
case CONNECT.FORGET_SINGLE :
|
case CONNECT.FORGET_SINGLE :
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
import { LOCATION_CHANGE } from 'react-router-redux';
|
import { LOCATION_CHANGE } from 'react-router-redux';
|
||||||
import * as NOTIFICATION from '../actions/constants/notification';
|
import * as NOTIFICATION from '../actions/constants/notification';
|
||||||
|
import { DEVICE } from 'trezor-connect';
|
||||||
|
|
||||||
type NotificationAction = {
|
type NotificationAction = {
|
||||||
label: string;
|
label: string;
|
||||||
@ -11,6 +12,7 @@ type NotificationAction = {
|
|||||||
|
|
||||||
type NotificationEntry = {
|
type NotificationEntry = {
|
||||||
+id: ?string;
|
+id: ?string;
|
||||||
|
+devicePath: ?string;
|
||||||
+type: string;
|
+type: string;
|
||||||
+title: string;
|
+title: string;
|
||||||
+message: string;
|
+message: string;
|
||||||
@ -33,6 +35,7 @@ const addNotification = (state: Array<NotificationEntry>, payload: any): Array<N
|
|||||||
const newState: Array<NotificationEntry> = state.filter(e => !e.cancelable);
|
const newState: Array<NotificationEntry> = state.filter(e => !e.cancelable);
|
||||||
newState.push({
|
newState.push({
|
||||||
id: payload.id,
|
id: payload.id,
|
||||||
|
devicePath: payload.devicePath,
|
||||||
type: payload.type,
|
type: payload.type,
|
||||||
title: payload.title.toString(),
|
title: payload.title.toString(),
|
||||||
message: payload.message.toString(),
|
message: payload.message.toString(),
|
||||||
@ -46,9 +49,11 @@ const addNotification = (state: Array<NotificationEntry>, payload: any): Array<N
|
|||||||
|
|
||||||
const closeNotification = (state: Array<NotificationEntry>, payload: any): Array<NotificationEntry> => {
|
const closeNotification = (state: Array<NotificationEntry>, payload: any): Array<NotificationEntry> => {
|
||||||
if (payload && typeof payload.id === 'string') {
|
if (payload && typeof payload.id === 'string') {
|
||||||
return state.filter(e => e.id !== payload.id);
|
return state.filter(entry => entry.id !== payload.id);
|
||||||
|
} else if (payload && typeof payload.devicePath === 'string') {
|
||||||
|
return state.filter(entry => entry.devicePath !== payload.devicePath);
|
||||||
} else {
|
} else {
|
||||||
return state.filter(e => !e.cancelable);
|
return state.filter(entry => !entry.cancelable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,6 +66,9 @@ export default function notification(state: Array<NotificationEntry> = initialSt
|
|||||||
case LOCATION_CHANGE :
|
case LOCATION_CHANGE :
|
||||||
case NOTIFICATION.CLOSE :
|
case NOTIFICATION.CLOSE :
|
||||||
return closeNotification(state, action.payload);
|
return closeNotification(state, action.payload);
|
||||||
|
|
||||||
|
case DEVICE.DISCONNECT :
|
||||||
|
return state.filter(entry => entry.devicePath !== action.device.path);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
|
@ -5,6 +5,8 @@ import * as RECEIVE from '../actions/constants/receive';
|
|||||||
|
|
||||||
export type State = {
|
export type State = {
|
||||||
+deviceState: ?string;
|
+deviceState: ?string;
|
||||||
|
+deviceId: ?string;
|
||||||
|
+deviceInstance: ?string;
|
||||||
+accountIndex: ?number;
|
+accountIndex: ?number;
|
||||||
+network: ?string;
|
+network: ?string;
|
||||||
location: string;
|
location: string;
|
||||||
@ -14,6 +16,8 @@ export type State = {
|
|||||||
|
|
||||||
export const initialState: State = {
|
export const initialState: State = {
|
||||||
deviceState: null,
|
deviceState: null,
|
||||||
|
deviceId: null,
|
||||||
|
deviceInstance: null,
|
||||||
accountIndex: null,
|
accountIndex: null,
|
||||||
network: null,
|
network: null,
|
||||||
location: '',
|
location: '',
|
||||||
|
@ -11,6 +11,8 @@ import { getFeeLevels } from '../actions/SendFormActions';
|
|||||||
|
|
||||||
export type State = {
|
export type State = {
|
||||||
+deviceState: ?string;
|
+deviceState: ?string;
|
||||||
|
+deviceId: ?string;
|
||||||
|
+deviceInstance: ?string;
|
||||||
+accountIndex: number;
|
+accountIndex: number;
|
||||||
+network: string;
|
+network: string;
|
||||||
+coinSymbol: string;
|
+coinSymbol: string;
|
||||||
@ -51,6 +53,8 @@ export type FeeLevel = {
|
|||||||
|
|
||||||
export const initialState: State = {
|
export const initialState: State = {
|
||||||
deviceState: null,
|
deviceState: null,
|
||||||
|
deviceId: null,
|
||||||
|
deviceInstance: null,
|
||||||
accountIndex: 0,
|
accountIndex: 0,
|
||||||
network: '',
|
network: '',
|
||||||
coinSymbol: '',
|
coinSymbol: '',
|
||||||
@ -83,11 +87,11 @@ export const initialState: State = {
|
|||||||
|
|
||||||
const onGasPriceUpdated = (state: State, action: any): State => {
|
const onGasPriceUpdated = (state: State, action: any): State => {
|
||||||
|
|
||||||
function getRandomInt(min, max) {
|
// function getRandomInt(min, max) {
|
||||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
// return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
}
|
// }
|
||||||
const newPrice = getRandomInt(10, 50).toString();
|
// const newPrice = getRandomInt(10, 50).toString();
|
||||||
//const newPrice = EthereumjsUnits.convert(action.gasPrice, 'wei', 'gwei');
|
const newPrice = EthereumjsUnits.convert(action.gasPrice, 'wei', 'gwei');
|
||||||
if (action.network === state.network && newPrice !== state.recommendedGasPrice) {
|
if (action.network === state.network && newPrice !== state.recommendedGasPrice) {
|
||||||
const newState: State = { ...state };
|
const newState: State = { ...state };
|
||||||
if (!state.untouched) {
|
if (!state.untouched) {
|
||||||
|
@ -5,6 +5,8 @@ import * as SUMMARY from '../actions/constants/summary';
|
|||||||
|
|
||||||
export type State = {
|
export type State = {
|
||||||
+deviceState: ?string;
|
+deviceState: ?string;
|
||||||
|
+deviceId: ?string;
|
||||||
|
+deviceInstance: ?string;
|
||||||
+accountIndex: ?number;
|
+accountIndex: ?number;
|
||||||
+network: ?string;
|
+network: ?string;
|
||||||
location: string;
|
location: string;
|
||||||
@ -15,6 +17,8 @@ export type State = {
|
|||||||
|
|
||||||
export const initialState: State = {
|
export const initialState: State = {
|
||||||
deviceState: null,
|
deviceState: null,
|
||||||
|
deviceId: null,
|
||||||
|
deviceInstance: null,
|
||||||
accountIndex: null,
|
accountIndex: null,
|
||||||
network: null,
|
network: null,
|
||||||
location: '',
|
location: '',
|
||||||
|
@ -7,6 +7,7 @@ import * as CONNECT from '../actions/constants/TrezorConnect';
|
|||||||
export type TrezorDevice = {
|
export type TrezorDevice = {
|
||||||
remember: boolean;
|
remember: boolean;
|
||||||
connected: boolean;
|
connected: boolean;
|
||||||
|
available: boolean; // device cannot be used because of features.passphrase_protection is different then expected (saved)
|
||||||
path: string;
|
path: string;
|
||||||
+label: string;
|
+label: string;
|
||||||
+state: string;
|
+state: string;
|
||||||
@ -58,6 +59,8 @@ export const findSelectedDevice = (state: State): ?TrezorDevice => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const isSavedDevice = (state: State, device: any): ?Array<TrezorDevice> => {
|
export const isSavedDevice = (state: State, device: any): ?Array<TrezorDevice> => {
|
||||||
const selected: ?SelectedDevice = state.selectedDevice;
|
const selected: ?SelectedDevice = state.selectedDevice;
|
||||||
if (!selected) return null;
|
if (!selected) return null;
|
||||||
@ -73,17 +76,36 @@ export const isSavedDevice = (state: State, device: any): ?Array<TrezorDevice> =
|
|||||||
}
|
}
|
||||||
|
|
||||||
const mergeDevices = (current: TrezorDevice, upcoming: Object): TrezorDevice => {
|
const mergeDevices = (current: TrezorDevice, upcoming: Object): TrezorDevice => {
|
||||||
|
|
||||||
|
// do not merge if passphrase protection was changed
|
||||||
|
// if (upcoming.features && current.features) {
|
||||||
|
// if (upcoming.features.passphrase_protection !== current.features.passphrase_protection) {
|
||||||
|
// // device settings has been changed, reset state
|
||||||
|
// // dev.state = null;
|
||||||
|
// // console.log("RESTETTTT STATE!");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
let instanceLabel = current.instanceLabel;
|
||||||
|
if (upcoming.label !== current.label) {
|
||||||
|
instanceLabel = upcoming.label
|
||||||
|
if (typeof current.instance === 'number') {
|
||||||
|
instanceLabel += ` (${current.instance})`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const dev: TrezorDevice = {
|
const dev: TrezorDevice = {
|
||||||
// ...current,
|
// ...current,
|
||||||
...upcoming,
|
...upcoming,
|
||||||
// make sure that instance specific variables will not be overridden
|
// make sure that instance specific variables will not be overridden
|
||||||
connected: typeof upcoming.connected === 'boolean' ? upcoming.connected : current.connected,
|
connected: typeof upcoming.connected === 'boolean' ? upcoming.connected : current.connected,
|
||||||
|
available: typeof upcoming.available === 'boolean' ? upcoming.available : current.available,
|
||||||
remember: typeof upcoming.remember === 'boolean' ? upcoming.remember : current.remember,
|
remember: typeof upcoming.remember === 'boolean' ? upcoming.remember : current.remember,
|
||||||
instance: current.instance,
|
instance: current.instance,
|
||||||
instanceLabel: current.instanceLabel,
|
instanceLabel,
|
||||||
state: current.state,
|
state: current.state,
|
||||||
acquiring: typeof upcoming.acquiring === 'boolean' ? upcoming.acquiring : current.acquiring,
|
acquiring: typeof upcoming.acquiring === 'boolean' ? upcoming.acquiring : current.acquiring,
|
||||||
ts: new Date().getTime(),
|
ts: typeof upcoming.ts === 'number' ? upcoming.ts : current.ts,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (upcoming.unacquired && current.state) {
|
if (upcoming.unacquired && current.state) {
|
||||||
@ -94,18 +116,11 @@ const mergeDevices = (current: TrezorDevice, upcoming: Object): TrezorDevice =>
|
|||||||
} else if (!upcoming.unacquired && current.unacquired) {
|
} else if (!upcoming.unacquired && current.unacquired) {
|
||||||
dev.instanceLabel = upcoming.label;
|
dev.instanceLabel = upcoming.label;
|
||||||
if (typeof dev.instance === 'number') {
|
if (typeof dev.instance === 'number') {
|
||||||
dev.instanceLabel = `${upcoming.label} #${dev.instance}`;
|
dev.instanceLabel = `${upcoming.label} TODO:(${dev.instance})`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (upcoming.features && current.features) {
|
|
||||||
console.log("CZEKIN PASS PROT");
|
|
||||||
if (upcoming.features.passphrase_protection !== current.features.passphrase_protection) {
|
|
||||||
// device settings has been changed, reset state
|
|
||||||
dev.state = null;
|
|
||||||
console.log("RESTETTTT STATE!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
@ -132,7 +147,40 @@ const addDevice = (state: State, device: Object): State => {
|
|||||||
|
|
||||||
if (affectedDevices.length > 0 ) {
|
if (affectedDevices.length > 0 ) {
|
||||||
// replace existing values
|
// replace existing values
|
||||||
const changedDevices: Array<TrezorDevice> = affectedDevices.map(d => mergeDevices(d, { ...device, connected: true} ));
|
// const changedDevices: Array<TrezorDevice> = affectedDevices.map(d => mergeDevices(d, { ...device, connected: true} ));
|
||||||
|
let cloneInstance: number = 1;
|
||||||
|
const changedDevices: Array<TrezorDevice> = affectedDevices.map(d => {
|
||||||
|
if (d.features.passphrase_protection === device.features.passphrase_protection) {
|
||||||
|
cloneInstance = 0;
|
||||||
|
return mergeDevices(d, { ...device, connected: true, available: true } );
|
||||||
|
} else {
|
||||||
|
if (d.instance && cloneInstance > 0) {
|
||||||
|
cloneInstance = d.instance + 1;
|
||||||
|
}
|
||||||
|
return mergeDevices(d, { ...d, connected: true, available: false } );
|
||||||
|
// return d;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (cloneInstance > 0) {
|
||||||
|
// TODO: instance should be calculated form affectedDevice
|
||||||
|
const instance = cloneInstance; //new Date().getTime();
|
||||||
|
|
||||||
|
const newDevice: TrezorDevice = {
|
||||||
|
...device,
|
||||||
|
acquiring: false,
|
||||||
|
remember: false,
|
||||||
|
connected: true,
|
||||||
|
available: true,
|
||||||
|
path: device.path,
|
||||||
|
label: device.label,
|
||||||
|
state: null,
|
||||||
|
instance,
|
||||||
|
instanceLabel: `${device.label} (${instance})`,
|
||||||
|
ts: new Date().getTime(),
|
||||||
|
}
|
||||||
|
changedDevices.push(newDevice);
|
||||||
|
}
|
||||||
newState.devices = otherDevices.concat(changedDevices);
|
newState.devices = otherDevices.concat(changedDevices);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -142,12 +190,13 @@ const addDevice = (state: State, device: Object): State => {
|
|||||||
acquiring: false,
|
acquiring: false,
|
||||||
remember: false,
|
remember: false,
|
||||||
connected: true,
|
connected: true,
|
||||||
|
available: true,
|
||||||
path: device.path,
|
path: device.path,
|
||||||
label: device.label,
|
label: device.label,
|
||||||
state: null,
|
state: null,
|
||||||
// instance: 0,
|
// instance: 0,
|
||||||
instanceLabel: device.label,
|
instanceLabel: device.label,
|
||||||
ts: 0,
|
ts: new Date().getTime(),
|
||||||
}
|
}
|
||||||
newState.devices.push(newDevice);
|
newState.devices.push(newDevice);
|
||||||
|
|
||||||
@ -184,11 +233,15 @@ const changeDevice = (state: State, device: Object): State => {
|
|||||||
let affectedDevices: Array<TrezorDevice> = [];
|
let affectedDevices: Array<TrezorDevice> = [];
|
||||||
let otherDevices: Array<TrezorDevice> = [];
|
let otherDevices: Array<TrezorDevice> = [];
|
||||||
if (device.features) {
|
if (device.features) {
|
||||||
affectedDevices = state.devices.filter(d => (d.features && d.features.device_id === device.features.device_id) || (d.path.length > 0 && d.path === device.path) );
|
affectedDevices = state.devices.filter(d =>
|
||||||
|
(d.features && d.features.device_id === device.features.device_id && d.features.passphrase_protection === device.features.passphrase_protection) ||
|
||||||
|
(d.path.length > 0 && d.path === device.path)
|
||||||
|
);
|
||||||
otherDevices = state.devices.filter(d => affectedDevices.indexOf(d) === -1);
|
otherDevices = state.devices.filter(d => affectedDevices.indexOf(d) === -1);
|
||||||
} else {
|
} else {
|
||||||
affectedDevices = state.devices.filter(d => d.path === device.path);
|
affectedDevices = state.devices.filter(d => !d.features && d.path === device.path);
|
||||||
otherDevices = state.devices.filter(d => d.path !== device.path);
|
otherDevices = state.devices.filter(d => affectedDevices.indexOf(d) === -1);
|
||||||
|
// otherDevices = state.devices.filter(d => d.path !== device.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (affectedDevices.length > 0) {
|
if (affectedDevices.length > 0) {
|
||||||
@ -226,13 +279,14 @@ const changeDevice = (state: State, device: Object): State => {
|
|||||||
const disconnectDevice = (state: State, device: Object): State => {
|
const disconnectDevice = (state: State, device: Object): State => {
|
||||||
|
|
||||||
const newState: State = { ...state };
|
const newState: State = { ...state };
|
||||||
const affectedDevices: Array<TrezorDevice> = state.devices.filter(d => d.path === device.path);
|
const affectedDevices: Array<TrezorDevice> = state.devices.filter(d => d.path === device.path || (d.features && device.features && d.features.device_id === device.features.device_id));
|
||||||
const otherDevices: Array<TrezorDevice> = state.devices.filter(d => affectedDevices.indexOf(d) === -1);
|
const otherDevices: Array<TrezorDevice> = state.devices.filter(d => affectedDevices.indexOf(d) === -1);
|
||||||
|
|
||||||
if (affectedDevices.length > 0) {
|
if (affectedDevices.length > 0) {
|
||||||
const acquiredDevices = affectedDevices.filter(d => !d.unacquired && d.state);
|
const acquiredDevices = affectedDevices.filter(d => !d.unacquired && d.state);
|
||||||
newState.devices = otherDevices.concat( acquiredDevices.map(d => {
|
newState.devices = otherDevices.concat( acquiredDevices.map(d => {
|
||||||
d.connected = false;
|
d.connected = false;
|
||||||
|
d.available = false;
|
||||||
d.isUsedElsewhere = false;
|
d.isUsedElsewhere = false;
|
||||||
d.featuresNeedsReload = false;
|
d.featuresNeedsReload = false;
|
||||||
d.acquiring = false;
|
d.acquiring = false;
|
||||||
@ -261,7 +315,7 @@ const forgetDevice = (state: State, action: any): State => {
|
|||||||
} else {
|
} else {
|
||||||
// remove all instances after disconnect (remember request declined)
|
// remove all instances after disconnect (remember request declined)
|
||||||
//newState.devices = state.devices.filter(d => d.path !== action.device.path);
|
//newState.devices = state.devices.filter(d => d.path !== action.device.path);
|
||||||
newState.devices = state.devices.filter(d => (d.features && d.features.device_id !== action.device.features.device_id) || (!d.features && d.path !== action.device.path));
|
newState.devices = state.devices.filter(d => d.remember || (d.features && d.features.device_id !== action.device.features.device_id) || (!d.features && d.path !== action.device.path));
|
||||||
}
|
}
|
||||||
|
|
||||||
return newState;
|
return newState;
|
||||||
@ -272,6 +326,7 @@ const devicesFromLocalStorage = (devices: Array<any>): Array<TrezorDevice> => {
|
|||||||
return {
|
return {
|
||||||
...d,
|
...d,
|
||||||
connected: false,
|
connected: false,
|
||||||
|
available: false,
|
||||||
path: '',
|
path: '',
|
||||||
acquiring: false,
|
acquiring: false,
|
||||||
featuresNeedsReload: false,
|
featuresNeedsReload: false,
|
||||||
@ -282,24 +337,33 @@ const devicesFromLocalStorage = (devices: Array<any>): Array<TrezorDevice> => {
|
|||||||
|
|
||||||
const duplicate = (state: State, device: any): State => {
|
const duplicate = (state: State, device: any): State => {
|
||||||
const newState: State = { ...state };
|
const newState: State = { ...state };
|
||||||
const affectedDevices: Array<TrezorDevice> = state.devices.filter(d => d.path === device.path);
|
const affectedDevices: Array<TrezorDevice> = state.devices.filter(d => d.features.device_id === device.features.device_id);
|
||||||
|
const instance = affectedDevices.reduce((inst, dev) => {
|
||||||
|
console.warn("REDUC", inst, dev);
|
||||||
|
return dev.instance ? dev.instance + 1 : inst;
|
||||||
|
}, 1);
|
||||||
|
|
||||||
|
console.warn("NEEEW INST", instance);
|
||||||
|
|
||||||
// if (affectedDevices.length > 0) {
|
// if (affectedDevices.length > 0) {
|
||||||
|
|
||||||
const newDevice: TrezorDevice = {
|
const newDevice: TrezorDevice = {
|
||||||
...device,
|
...device,
|
||||||
state: null,
|
acquiring: false,
|
||||||
remember: device.remember,
|
remember: false,
|
||||||
connected: device.connected,
|
connected: device.connected,
|
||||||
|
available: device.available,
|
||||||
path: device.path,
|
path: device.path,
|
||||||
label: device.label,
|
label: device.label,
|
||||||
instance: new Date().getTime(),
|
state: null,
|
||||||
instanceLabel: device.instanceLabel,
|
instance,
|
||||||
ts: 0,
|
instanceLabel: `${device.label} (${instance})`,
|
||||||
|
ts: new Date().getTime(),
|
||||||
}
|
}
|
||||||
newState.devices.push(newDevice);
|
newState.devices.push(newDevice);
|
||||||
newState.selectedDevice = {
|
newState.selectedDevice = {
|
||||||
id: newDevice.features.device_id,
|
id: newDevice.features.device_id,
|
||||||
instance: newDevice.instance
|
instance
|
||||||
}
|
}
|
||||||
//}
|
//}
|
||||||
|
|
||||||
@ -307,6 +371,19 @@ const duplicate = (state: State, device: any): State => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const onSelectDevice = (state: State, action: any): State => {
|
||||||
|
const newState: State = { ...state };
|
||||||
|
newState.selectedDevice = action.payload;
|
||||||
|
|
||||||
|
const selected = findSelectedDevice(newState);
|
||||||
|
if (selected) {
|
||||||
|
selected.ts = new Date().getTime();
|
||||||
|
console.warn("APDEJT SELECTED!", selected.instanceLabel, selected.ts)
|
||||||
|
}
|
||||||
|
|
||||||
|
return newState;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export default function connect(state: State = initialState, action: any): any {
|
export default function connect(state: State = initialState, action: any): any {
|
||||||
|
|
||||||
@ -323,10 +400,11 @@ export default function connect(state: State = initialState, action: any): any {
|
|||||||
|
|
||||||
|
|
||||||
case CONNECT.SELECT_DEVICE :
|
case CONNECT.SELECT_DEVICE :
|
||||||
return {
|
return onSelectDevice(state, action);
|
||||||
...state,
|
// return {
|
||||||
selectedDevice: action.payload
|
// ...state,
|
||||||
}
|
// selectedDevice: action.payload
|
||||||
|
// }
|
||||||
|
|
||||||
case CONNECT.INITIALIZATION_ERROR :
|
case CONNECT.INITIALIZATION_ERROR :
|
||||||
return {
|
return {
|
||||||
@ -378,7 +456,7 @@ export default function connect(state: State = initialState, action: any): any {
|
|||||||
return disconnectDevice(state, action.device);
|
return disconnectDevice(state, action.device);
|
||||||
|
|
||||||
case DEVICE.CHANGED :
|
case DEVICE.CHANGED :
|
||||||
return changeDevice(state, { ...action.device, connected: true });
|
return changeDevice(state, { ...action.device, connected: true, available: true });
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
|
@ -1,26 +1,44 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { ON_RESIZE, TOGGLE_DEVICE_DROPDOWN, RESIZE_CONTAINER } from '../actions/AppActions';
|
|
||||||
import * as WEB3 from '../actions/constants/Web3';
|
import * as WEB3 from '../actions/constants/Web3';
|
||||||
|
import * as WALLET from '../actions/constants/wallet';
|
||||||
const WIDTH: number = 1080;
|
|
||||||
const HEIGHT: number = 1920;
|
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
network: string;
|
ready: boolean;
|
||||||
device: string;
|
dropdownOpened: boolean;
|
||||||
|
initialUrl: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState: Object = {
|
const initialState: Object = {
|
||||||
|
ready: false,
|
||||||
|
dropdownOpened: false,
|
||||||
|
initialParams: null,
|
||||||
|
initialPathname: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function wallet(state: Object = initialState, action: Object): any {
|
export default function wallet(state: Object = initialState, action: Object): any {
|
||||||
switch(action.type) {
|
switch(action.type) {
|
||||||
|
|
||||||
|
case WALLET.SET_INITIAL_URL :
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
initialParams: action.params,
|
||||||
|
initialPathname: action.pathname
|
||||||
|
}
|
||||||
|
|
||||||
|
case WEB3.READY :
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
ready: true
|
||||||
|
}
|
||||||
|
|
||||||
|
case WALLET.TOGGLE_DEVICE_DROPDOWN :
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
dropdownOpened: action.opened
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
import { combineReducers } from 'redux';
|
import { combineReducers } from 'redux';
|
||||||
import { routerReducer } from 'react-router-redux';
|
import { routerReducer } from 'react-router-redux';
|
||||||
|
|
||||||
import DOM from './AppReducer.js';
|
|
||||||
import log from './LogReducer.js';
|
import log from './LogReducer.js';
|
||||||
import localStorage from './LocalStorageReducer.js';
|
import localStorage from './LocalStorageReducer.js';
|
||||||
import connect from './TrezorConnectReducer.js';
|
import connect from './TrezorConnectReducer.js';
|
||||||
@ -12,7 +11,7 @@ import notifications from './NotificationReducer.js';
|
|||||||
import modal from './ModalReducer.js';
|
import modal from './ModalReducer.js';
|
||||||
import web3 from './Web3Reducer.js';
|
import web3 from './Web3Reducer.js';
|
||||||
import accounts from './AccountsReducer.js';
|
import accounts from './AccountsReducer.js';
|
||||||
import accountDetail from './AccountDetailReducer.js';
|
import abstractAccount from './AbstractAccountReducer.js';
|
||||||
import sendForm from './SendFormReducer.js';
|
import sendForm from './SendFormReducer.js';
|
||||||
import receive from './ReceiveReducer.js';
|
import receive from './ReceiveReducer.js';
|
||||||
import summary from './SummaryReducer.js';
|
import summary from './SummaryReducer.js';
|
||||||
@ -20,10 +19,10 @@ import tokens from './TokensReducer.js';
|
|||||||
import discovery from './DiscoveryReducer.js';
|
import discovery from './DiscoveryReducer.js';
|
||||||
import pending from './PendingTxReducer.js';
|
import pending from './PendingTxReducer.js';
|
||||||
import fiat from './FiatRateReducer.js';
|
import fiat from './FiatRateReducer.js';
|
||||||
|
import wallet from './WalletReducer.js';
|
||||||
|
|
||||||
export default combineReducers({
|
export default combineReducers({
|
||||||
router: routerReducer,
|
router: routerReducer,
|
||||||
DOM,
|
|
||||||
log,
|
log,
|
||||||
localStorage,
|
localStorage,
|
||||||
connect,
|
connect,
|
||||||
@ -31,12 +30,13 @@ export default combineReducers({
|
|||||||
modal,
|
modal,
|
||||||
web3,
|
web3,
|
||||||
accounts,
|
accounts,
|
||||||
accountDetail,
|
abstractAccount,
|
||||||
sendForm,
|
sendForm,
|
||||||
receive,
|
receive,
|
||||||
summary,
|
summary,
|
||||||
tokens,
|
tokens,
|
||||||
discovery,
|
discovery,
|
||||||
pending,
|
pending,
|
||||||
fiat
|
fiat,
|
||||||
|
wallet
|
||||||
});
|
});
|
@ -7,23 +7,18 @@ import { Provider } from 'react-redux';
|
|||||||
import { ConnectedRouter } from 'react-router-redux';
|
import { ConnectedRouter } from 'react-router-redux';
|
||||||
import store, { history } from '../store';
|
import store, { history } from '../store';
|
||||||
|
|
||||||
import {
|
import LandingPageContainer from '../components/landing';
|
||||||
LandingPageContainer,
|
import WalletContainer from '../components/wallet';
|
||||||
WalletContainer,
|
import BootloaderContainer from '../components/wallet/Bootloader';
|
||||||
|
import AcquireContainer from '../components/wallet/Acquire';
|
||||||
|
|
||||||
AcquireContainer,
|
import DashboardContainer from '../components/wallet/Dashboard';
|
||||||
BootloaderContainer,
|
import SummaryContainer from '../components/wallet/summary';
|
||||||
|
import SendFormContainer from '../components/wallet/send';
|
||||||
DashboardContainer,
|
import ReceiveContainer from '../components/wallet/Receive';
|
||||||
|
import SignVerifyContainer from '../components/wallet/SignVerify';
|
||||||
HistoryContainer,
|
import DeviceSettingsContainer from '../components/wallet/DeviceSettings';
|
||||||
SendFormContainer,
|
import WalletSettingsContainer from '../components/wallet/WalletSettings';
|
||||||
ReceiveContainer,
|
|
||||||
SignVerifyContainer,
|
|
||||||
SettingsContainer,
|
|
||||||
} from '../containers';
|
|
||||||
|
|
||||||
import SummaryContainer from '../components/wallet/summary/SummaryContainer';
|
|
||||||
|
|
||||||
export default (
|
export default (
|
||||||
<Provider store={ store }>
|
<Provider store={ store }>
|
||||||
@ -34,20 +29,19 @@ export default (
|
|||||||
<Route exact path="/import" component={ LandingPageContainer } />
|
<Route exact path="/import" component={ LandingPageContainer } />
|
||||||
<Route>
|
<Route>
|
||||||
<WalletContainer>
|
<WalletContainer>
|
||||||
|
<Route exact path="/settings" component={ WalletSettingsContainer } />
|
||||||
<Route exact path="/device/:device/" component={ DashboardContainer } />
|
<Route exact path="/device/:device/" component={ DashboardContainer } />
|
||||||
<Route exact path="/device/:device/network/:network" component={ DashboardContainer } />
|
<Route exact path="/device/:device/network/:network" component={ DashboardContainer } />
|
||||||
<Route exact path="/device/:device/acquire" component={ AcquireContainer } />
|
<Route exact path="/device/:device/acquire" component={ AcquireContainer } />
|
||||||
<Route exact path="/device/:device/bootloader" component={ BootloaderContainer } />
|
<Route exact path="/device/:device/bootloader" component={ BootloaderContainer } />
|
||||||
|
<Route exact path="/device/:device/settings" component={ DeviceSettingsContainer } />
|
||||||
<Route exact path="/device/:device/network/:network/address/:address" component={ SummaryContainer } />
|
<Route exact path="/device/:device/network/:network/address/:address" component={ SummaryContainer } />
|
||||||
<Route path="/device/:device/network/:network/address/:address/send" component={ SendFormContainer } />
|
<Route path="/device/:device/network/:network/address/:address/send" component={ SendFormContainer } />
|
||||||
<Route path="/device/:device/network/:network/address/:address/send/override" component={ SendFormContainer } />
|
<Route path="/device/:device/network/:network/address/:address/send/override" component={ SendFormContainer } />
|
||||||
<Route path="/device/:device/network/:network/address/:address/receive" component={ ReceiveContainer } />
|
<Route path="/device/:device/network/:network/address/:address/receive" component={ ReceiveContainer } />
|
||||||
<Route path="/device/:device/network/:network/address/:address/signverify" component={ SignVerifyContainer } />
|
<Route path="/device/:device/network/:network/address/:address/signverify" component={ SignVerifyContainer } />
|
||||||
{/* <Route path="/device/:device/address/:address/history" component={ HistoryContainer } /> */}
|
|
||||||
|
|
||||||
</WalletContainer>
|
</WalletContainer>
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/settings" component={ SettingsContainer } />
|
|
||||||
</Switch>
|
</Switch>
|
||||||
</ConnectedRouter>
|
</ConnectedRouter>
|
||||||
</Provider>
|
</Provider>
|
||||||
|
@ -1,174 +0,0 @@
|
|||||||
/* @flo */
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
//http://ropsten.etherscan.io/api?module=account&action=txlist&address=0x98ead4bd2fbbb0cf0b49459aa0510ef53faa6cad&startblock=0&endblock=99999999&sort=asc&apikey=89IZG471H8ITVXY377I2QWJIT2D62DGG9Z
|
|
||||||
|
|
||||||
import { LOCATION_CHANGE, push } from 'react-router-redux';
|
|
||||||
import { httpRequest } from '../utils/networkUtils';
|
|
||||||
import * as ACTIONS from '../actions/index';
|
|
||||||
import { getBalance } from '../actions/Web3Actions';
|
|
||||||
|
|
||||||
const API_KEY: string = '89IZG471H8ITVXY377I2QWJIT2D62DGG9Z';
|
|
||||||
//const API: string = `http://ropsten.etherscan.io/api?module=account&action=txlist&startblock=0&endblock=99999999&sort=asc&apikey=89IZG471H8ITVXY377I2QWJIT2D62DGG9Z`;
|
|
||||||
const API: string = `http://ropsten.etherscan.io/api?module=account&action=txlist&startblock=0&endblock=99999999&sort=desc&apikey=${API_KEY}`;
|
|
||||||
|
|
||||||
export const getTransactionHistory = async (address: string): Promise<Array<any>> => {
|
|
||||||
const json = await httpRequest(`${API}&address=${address}`);
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
const getTransactionStatus = async (txid: string): Promise<Array<any>> => {
|
|
||||||
//https://ropsten.etherscan.io/api?module=proxy&action=eth_getTransactionByHash&txhash=0x1e2910a262b1008d0616a0beb24c1a491d78771baa54a33e66065e03b1f46bc1&apikey=YourApiKeyToken
|
|
||||||
const url: string = `https://ropsten.etherscan.io/api?module=proxy&action=eth_getTransactionByHash&apikey=${API_KEY}`
|
|
||||||
//const url: string = `https://ropsten.etherscan.io/api?module=transaction&action=getstatus&apikey=${API_KEY}`
|
|
||||||
const json = await httpRequest(`${url}&txhash=${txid}`);
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
const getTokenHistory = async (tokenAddress, address) => {
|
|
||||||
|
|
||||||
// 0x58cda554935e4a1f2acbe15f8757400af275e084
|
|
||||||
// 0x000000000000000000000000 + 98ead4bd2fbbb0cf0b49459aa0510ef53faa6cad
|
|
||||||
let url: string = 'https://ropsten.etherscan.io/api?module=logs&action=getLogs';
|
|
||||||
url += '&fromBlock=0&toBlock=latest';
|
|
||||||
url += `&address=${tokenAddress}`;
|
|
||||||
url += '&topic0=0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';
|
|
||||||
url += `&topic2=${ address }`;
|
|
||||||
// https://api.etherscan.io/api?module=logs&action=getLogs
|
|
||||||
// &fromBlock=0
|
|
||||||
// &toBlock=latest
|
|
||||||
// &address=[Token Contract Address]
|
|
||||||
// &topic0=0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
|
|
||||||
// &topic1=[From Address, padded to 32 bytes - optional]
|
|
||||||
// &topic2=[To Address, padded to 32 bytes - optional]
|
|
||||||
|
|
||||||
console.log("TOKENURL", url);
|
|
||||||
const json = await httpRequest(url);
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const loadTokenHistory = (address): Promise<any> => {
|
|
||||||
// https://ropsten.etherscan.io/apis#logs
|
|
||||||
return async (dispatch, getState): Promise<any> => {
|
|
||||||
const tkn = '0x58cda554935e4a1f2acbe15f8757400af275e084';
|
|
||||||
const ad = '0x00000000000000000000000098ead4bd2fbbb0cf0b49459aa0510ef53faa6cad';
|
|
||||||
const incoming = await getTokenHistory(tkn, ad);
|
|
||||||
|
|
||||||
console.log("TOKEN HIST!", JSON.parse(incoming) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const loadTransactionStatus = (txid): Promise<any> => {
|
|
||||||
return async (dispatch, getState): Promise<any> => {
|
|
||||||
const json = await getTransactionStatus(txid);
|
|
||||||
const status = JSON.parse(json);
|
|
||||||
|
|
||||||
console.error("TXSTAT", status)
|
|
||||||
|
|
||||||
if (status.result.blockHash) {
|
|
||||||
// find address with pending tx
|
|
||||||
const { addresses } = getState().addresses;
|
|
||||||
for (let addr of addresses) {
|
|
||||||
if (addr.findPendingTx(txid)) {
|
|
||||||
dispatch( getBalance(addr) );
|
|
||||||
|
|
||||||
const txType = status.result.from === addr.address ? 'out' : 'in';
|
|
||||||
const txAddress = txType === 'out' ? status.result.to : status.result.from;
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.ADDRESS_ADD_TO_HISTORY,
|
|
||||||
address: addr,
|
|
||||||
entry: {
|
|
||||||
txid: status.result.hash,
|
|
||||||
type: txType,
|
|
||||||
timestamp: '0',
|
|
||||||
address: txAddress,
|
|
||||||
value: status.result.value
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//dispatch( loadHistory(addr, 3000) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.TX_STATUS_OK,
|
|
||||||
txid
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (status.status === "1" && status.message === "OK") {
|
|
||||||
// if (status.result.isError === "0") {
|
|
||||||
// dispatch({
|
|
||||||
// type: ACTIONS.TX_STATUS_OK,
|
|
||||||
// txid
|
|
||||||
// });
|
|
||||||
// } else {
|
|
||||||
// dispatch({
|
|
||||||
// type: ACTIONS.TX_STATUS_ERROR,
|
|
||||||
// txid,
|
|
||||||
// error: status.errDescription
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// dispatch({
|
|
||||||
// type: ACTIONS.TX_STATUS_UNKNOWN,
|
|
||||||
// txid,
|
|
||||||
// status
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const loadHistory = (address, delay): void => {
|
|
||||||
return async (dispatch, getState) => {
|
|
||||||
|
|
||||||
// const json = await getTransactionStatus('0x2113e578497f3486944566e2417b5ac3b31d7e76f71557ae0626e2a6fe191e58');
|
|
||||||
// console.log("JSON!", json)
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (delay) {
|
|
||||||
console.warn("-----PRELOAD with delay", address)
|
|
||||||
await new Promise(resolve => {
|
|
||||||
setTimeout(resolve, delay);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const history = await getTransactionHistory(address.address);
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.ADDRESS_SET_HISTORY,
|
|
||||||
address,
|
|
||||||
history
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const EtherscanService = store => next => action => {
|
|
||||||
|
|
||||||
next(action);
|
|
||||||
|
|
||||||
if (action.type === LOCATION_CHANGE) {
|
|
||||||
|
|
||||||
const { location } = store.getState().router;
|
|
||||||
const { addresses } = store.getState().addresses;
|
|
||||||
|
|
||||||
if (location) {
|
|
||||||
const parts = location.pathname.split("/");
|
|
||||||
if (parts.length === 3 && parts[1] === "address") {
|
|
||||||
const addressId = parseInt(parts[2]);
|
|
||||||
|
|
||||||
if (!isNaN(addressId) && addresses[addressId]) {
|
|
||||||
//store.dispatch( loadHistory( addresses[addressId] ) );
|
|
||||||
//store.dispatch( loadTokenHistory( addresses[addressId] ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
//console.error("ETH", parts, "id", parts.length, parts.length === 3 && parts[1] === "address");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default EtherscanService;
|
|
@ -111,6 +111,7 @@ const LocalStorageService = (store: any) => (next: any) => (action: any) => {
|
|||||||
case DEVICE.CHANGED :
|
case DEVICE.CHANGED :
|
||||||
case DEVICE.DISCONNECT :
|
case DEVICE.DISCONNECT :
|
||||||
case CONNECT.AUTH_DEVICE :
|
case CONNECT.AUTH_DEVICE :
|
||||||
|
case CONNECT.SELECT_DEVICE :
|
||||||
save(store.dispatch, store.getState);
|
save(store.dispatch, store.getState);
|
||||||
//store.dispatch( LocalStorageActions.save('devices', JSON.stringify( store.getState().connect.devices.filter(d => d.remember === true && !d.unacquired) ) ) );
|
//store.dispatch( LocalStorageActions.save('devices', JSON.stringify( store.getState().connect.devices.filter(d => d.remember === true && !d.unacquired) ) ) );
|
||||||
// store.dispatch( LocalStorageActions.save('selectedDevice', JSON.stringify( store.getState().connect.selectedDevice ) ) );
|
// store.dispatch( LocalStorageActions.save('selectedDevice', JSON.stringify( store.getState().connect.selectedDevice ) ) );
|
||||||
|
@ -4,8 +4,9 @@
|
|||||||
import pathToRegexp from 'path-to-regexp';
|
import pathToRegexp from 'path-to-regexp';
|
||||||
import { DEVICE } from 'trezor-connect';
|
import { DEVICE } from 'trezor-connect';
|
||||||
import { LOCATION_CHANGE, push, replace } from 'react-router-redux';
|
import { LOCATION_CHANGE, push, replace } from 'react-router-redux';
|
||||||
import { ON_BEFORE_UNLOAD } from '../actions/AppActions';
|
|
||||||
import * as CONNECT from '../actions/constants/TrezorConnect';
|
import * as CONNECT from '../actions/constants/TrezorConnect';
|
||||||
|
import * as WALLET from '../actions/constants/wallet';
|
||||||
|
import * as NotificationActions from '../actions/NotificationActions';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Middleware used for init application and managing router path.
|
* Middleware used for init application and managing router path.
|
||||||
@ -66,25 +67,25 @@ let __unloading: boolean = false;
|
|||||||
|
|
||||||
const RouterService = (store: any) => (next: any) => (action: any) => {
|
const RouterService = (store: any) => (next: any) => (action: any) => {
|
||||||
|
|
||||||
if (action.type === ON_BEFORE_UNLOAD) {
|
if (action.type === WALLET.ON_BEFORE_UNLOAD) {
|
||||||
__unloading = true;
|
__unloading = true;
|
||||||
} else if (action.type === LOCATION_CHANGE && !__unloading) {
|
} else if (action.type === LOCATION_CHANGE && !__unloading) {
|
||||||
|
|
||||||
const { location } = store.getState().router;
|
const { location } = store.getState().router;
|
||||||
const web3 = store.getState().web3;
|
const web3 = store.getState().web3;
|
||||||
const { devices, error } = store.getState().connect;
|
const { devices, error } = store.getState().connect;
|
||||||
const { opened } = store.getState().modal;
|
const isModalOpened: boolean = store.getState().modal.opened;
|
||||||
|
|
||||||
let redirectPath: ?string;
|
let redirectPath: ?string;
|
||||||
// first (initial) event after app loads
|
// first event after application loads
|
||||||
if (!location) {
|
if (!location) {
|
||||||
|
|
||||||
action.payload.state = {
|
store.dispatch({
|
||||||
initURL: action.payload.pathname,
|
type: WALLET.SET_INITIAL_URL,
|
||||||
initSearch: action.payload.search
|
pathname: action.payload.pathname,
|
||||||
}
|
params: pathToParams(action.payload.pathname)
|
||||||
|
});
|
||||||
// check if there are initial parameters in url (network/ device / account)
|
|
||||||
if (action.payload.search.length > 0) {
|
if (action.payload.search.length > 0) {
|
||||||
// save it in WalletReducer, after device detection will redirect to this request
|
// save it in WalletReducer, after device detection will redirect to this request
|
||||||
redirectPath = '/';
|
redirectPath = '/';
|
||||||
@ -98,7 +99,7 @@ const RouterService = (store: any) => (next: any) => (action: any) => {
|
|||||||
// if web3 wasn't initialized yet or there are no devices attached or initialization error occurs
|
// if web3 wasn't initialized yet or there are no devices attached or initialization error occurs
|
||||||
const landingPage: boolean = web3.length < 1 || devices.length < 1 || error;
|
const landingPage: boolean = web3.length < 1 || devices.length < 1 || error;
|
||||||
|
|
||||||
if (opened && action.payload.pathname !== location.pathname) {
|
if (isModalOpened && action.payload.pathname !== location.pathname) {
|
||||||
redirectPath = location.pathname;
|
redirectPath = location.pathname;
|
||||||
console.warn("Modal still opened");
|
console.warn("Modal still opened");
|
||||||
} else if (landingPage) {
|
} else if (landingPage) {
|
||||||
@ -113,7 +114,7 @@ const RouterService = (store: any) => (next: any) => (action: any) => {
|
|||||||
// TODO: switch to first device?
|
// TODO: switch to first device?
|
||||||
// redirectPath = `/device/${ devices[0].path }`;
|
// redirectPath = `/device/${ devices[0].path }`;
|
||||||
redirectPath = location.pathname;
|
redirectPath = location.pathname;
|
||||||
} else {
|
} else if (requestedParams.device) {
|
||||||
|
|
||||||
if (currentParams.device !== requestedParams.device || currentParams.deviceInstance !== requestedParams.deviceInstance) {
|
if (currentParams.device !== requestedParams.device || currentParams.deviceInstance !== requestedParams.deviceInstance) {
|
||||||
store.dispatch({
|
store.dispatch({
|
||||||
@ -146,7 +147,8 @@ const RouterService = (store: any) => (next: any) => (action: any) => {
|
|||||||
} else {
|
} else {
|
||||||
action.payload.params = requestedParams;
|
action.payload.params = requestedParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
store.dispatch( NotificationActions.clear(currentParams, requestedParams) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass all actions through by default
|
// Pass all actions through by default
|
||||||
|
@ -11,13 +11,14 @@ import * as WEB3 from '../actions/constants/Web3';
|
|||||||
import * as STORAGE from '../actions/constants/LocalStorage';
|
import * as STORAGE from '../actions/constants/LocalStorage';
|
||||||
import * as CONNECT from '../actions/constants/TrezorConnect';
|
import * as CONNECT from '../actions/constants/TrezorConnect';
|
||||||
import * as NOTIFICATION from '../actions/constants/notification';
|
import * as NOTIFICATION from '../actions/constants/notification';
|
||||||
import * as ACTIONS from '../actions';
|
import * as MODAL from '../actions/constants/Modal';
|
||||||
|
|
||||||
|
|
||||||
const TrezorConnectService = (store: any) => (next: any) => (action: any) => {
|
const TrezorConnectService = (store: any) => (next: any) => (action: any) => {
|
||||||
|
|
||||||
const prevState = store.getState().connect;
|
const prevState = store.getState().connect;
|
||||||
const prevModalState = store.getState().modal;
|
const prevModalState = store.getState().modal;
|
||||||
|
const prevRouterState = store.getState().router;
|
||||||
|
|
||||||
next(action);
|
next(action);
|
||||||
|
|
||||||
@ -25,8 +26,14 @@ const TrezorConnectService = (store: any) => (next: any) => (action: any) => {
|
|||||||
store.dispatch( TrezorConnectActions.init() );
|
store.dispatch( TrezorConnectActions.init() );
|
||||||
|
|
||||||
} else if (action.type === TRANSPORT.ERROR) {
|
} else if (action.type === TRANSPORT.ERROR) {
|
||||||
store.dispatch( push('/') );
|
// TODO: check if modal is open
|
||||||
} else if (action.type === TRANSPORT.START && store.getState().web3.length > 0 && prevState.devices.length > 0) {
|
// store.dispatch( push('/') );
|
||||||
|
// } else if (action.type === TRANSPORT.START && store.getState().web3.length > 0 && prevState.devices.length > 0) {
|
||||||
|
// store.dispatch( TrezorConnectActions.postInit() );
|
||||||
|
} else if (action.type === TRANSPORT.START && store.getState().web3.length < 1) {
|
||||||
|
//store.dispatch( TrezorConnectActions.postInit() );
|
||||||
|
store.dispatch( initWeb3() );
|
||||||
|
} else if (action.type === WEB3.READY) {
|
||||||
store.dispatch( TrezorConnectActions.postInit() );
|
store.dispatch( TrezorConnectActions.postInit() );
|
||||||
} else if (action.type === TRANSPORT.UNREADABLE) {
|
} else if (action.type === TRANSPORT.UNREADABLE) {
|
||||||
store.dispatch({
|
store.dispatch({
|
||||||
@ -34,22 +41,16 @@ const TrezorConnectService = (store: any) => (next: any) => (action: any) => {
|
|||||||
payload: {
|
payload: {
|
||||||
type: 'error',
|
type: 'error',
|
||||||
title: 'Unreadable HID device',
|
title: 'Unreadable HID device',
|
||||||
message: 'What to do?',
|
message: '',
|
||||||
cancelable: true,
|
cancelable: true,
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
} else if (action.type === WEB3.READY) {
|
|
||||||
store.dispatch( TrezorConnectActions.postInit() );
|
|
||||||
|
|
||||||
} else if (action.type === DEVICE.DISCONNECT) {
|
} else if (action.type === DEVICE.DISCONNECT) {
|
||||||
store.dispatch( TrezorConnectActions.deviceDisconnect(action.device) );
|
store.dispatch( TrezorConnectActions.deviceDisconnect(action.device) );
|
||||||
|
|
||||||
} else if (action.type === CONNECT.REMEMBER_REQUEST) {
|
} else if (action.type === CONNECT.REMEMBER_REQUEST) {
|
||||||
// TODO:
|
// TODO: 2 modals at once
|
||||||
if (prevModalState.opened && prevModalState.windowType === CONNECT.REMEMBER_REQUEST) {
|
if (prevModalState.opened && prevModalState.windowType === CONNECT.REMEMBER_REQUEST) {
|
||||||
|
|
||||||
|
|
||||||
store.dispatch({
|
store.dispatch({
|
||||||
type: CONNECT.FORGET,
|
type: CONNECT.FORGET,
|
||||||
device: store.getState().modal.device
|
device: store.getState().modal.device
|
||||||
@ -82,6 +83,7 @@ const TrezorConnectService = (store: any) => (next: any) => (action: any) => {
|
|||||||
// we need to change route
|
// we need to change route
|
||||||
if (prevState.selectedDevice) {
|
if (prevState.selectedDevice) {
|
||||||
if (!action.device.unacquired && action.device.path === prevState.selectedDevice.id) {
|
if (!action.device.unacquired && action.device.path === prevState.selectedDevice.id) {
|
||||||
|
console.warn("TODO: here! better")
|
||||||
store.dispatch( TrezorConnectActions.onSelectDevice(action.device) );
|
store.dispatch( TrezorConnectActions.onSelectDevice(action.device) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,7 +98,7 @@ const TrezorConnectService = (store: any) => (next: any) => (action: any) => {
|
|||||||
if (modal.opened && modal.windowType === CONNECT.REMEMBER_REQUEST) {
|
if (modal.opened && modal.windowType === CONNECT.REMEMBER_REQUEST) {
|
||||||
if (action.device.features && modal.device.features.device_id === action.device.features.device_id) {
|
if (action.device.features && modal.device.features.device_id === action.device.features.device_id) {
|
||||||
store.dispatch({
|
store.dispatch({
|
||||||
type: ACTIONS.CLOSE_MODAL,
|
type: MODAL.CLOSE,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
store.dispatch({
|
store.dispatch({
|
||||||
@ -113,6 +115,7 @@ const TrezorConnectService = (store: any) => (next: any) => (action: any) => {
|
|||||||
store.dispatch( TrezorConnectActions.onDuplicateDevice() );
|
store.dispatch( TrezorConnectActions.onDuplicateDevice() );
|
||||||
|
|
||||||
} else if (action.type === DEVICE.ACQUIRED || action.type === CONNECT.SELECT_DEVICE) {
|
} else if (action.type === DEVICE.ACQUIRED || action.type === CONNECT.SELECT_DEVICE) {
|
||||||
|
console.warn("here!!!!!", action.type)
|
||||||
store.dispatch( TrezorConnectActions.getSelectedDeviceState() );
|
store.dispatch( TrezorConnectActions.getSelectedDeviceState() );
|
||||||
|
|
||||||
} else if (action.type === CONNECT.COIN_CHANGED) {
|
} else if (action.type === CONNECT.COIN_CHANGED) {
|
||||||
|
@ -1,238 +0,0 @@
|
|||||||
/* @flow */
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import Web3 from 'web3';
|
|
||||||
import { LOCATION_CHANGE } from 'react-router-redux';
|
|
||||||
import * as ACTIONS from '../actions/index';
|
|
||||||
import { getBalance, getGasPrice, getTransactionReceipt } from '../actions/Web3Actions';
|
|
||||||
import { loadTransactionStatus } from './EtherscanService';
|
|
||||||
import BigNumber from 'bignumber.js';
|
|
||||||
|
|
||||||
let web3: Web3;
|
|
||||||
|
|
||||||
// export const getGasPrice = (): Promise<BigNumber> => {
|
|
||||||
// return (dispatch, getState) => {
|
|
||||||
// web3.eth.getGasPrice((error, gasPrice) => {
|
|
||||||
// if (!error) {
|
|
||||||
// dispatch({
|
|
||||||
// type: 'update_gas',
|
|
||||||
// gasPrice: web3.fromWei(gasPrice.toString(), 'gwei')
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Web3Service = store => next => action => {
|
|
||||||
|
|
||||||
next(action);
|
|
||||||
|
|
||||||
switch (action.type) {
|
|
||||||
|
|
||||||
case 'WEB_2_START' :
|
|
||||||
if (web3) break;
|
|
||||||
|
|
||||||
//web3 = new Web3(window.web3.currentProvider);
|
|
||||||
//web3 = new Web3(new Web3.providers.HttpProvider("https://api.myetherapi.com/rop"));
|
|
||||||
web3 = new Web3(new Web3.providers.HttpProvider("https://ropsten.infura.io2/QGyVKozSUEh2YhL4s2G4"));
|
|
||||||
//web3 = new Web3( new Web3.providers.HttpProvider("ws://34.230.234.51:30303") );
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*store.dispatch( getGasPrice() );
|
|
||||||
|
|
||||||
|
|
||||||
const latestBlockFilter = web3.eth.filter('latest');
|
|
||||||
latestBlockFilter.watch((error, blockHash) => {
|
|
||||||
|
|
||||||
const { addresses, pendingTxs } = store.getState().addresses;
|
|
||||||
|
|
||||||
for (const addr of addresses) {
|
|
||||||
store.dispatch( getBalance(addr) );
|
|
||||||
}
|
|
||||||
|
|
||||||
store.dispatch( getGasPrice() );
|
|
||||||
|
|
||||||
if (pendingTxs.length > 0) {
|
|
||||||
for (const tx of pendingTxs) {
|
|
||||||
store.dispatch( getTransactionReceipt(tx) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// store.dispatch({
|
|
||||||
// type: 'web3__init',
|
|
||||||
// web3
|
|
||||||
// });
|
|
||||||
|
|
||||||
// store.dispatch({
|
|
||||||
// type: 'update_gas',
|
|
||||||
// gasPrice: web3.fromWei(web3.eth.gasPrice, 'gwei')
|
|
||||||
// })
|
|
||||||
|
|
||||||
/*
|
|
||||||
{
|
|
||||||
"dd62ed3e": "allowance(address,address)",
|
|
||||||
"095ea7b3": "approve(address,uint256)",
|
|
||||||
"cae9ca51": "approveAndCall(address,uint256,bytes)",
|
|
||||||
"70a08231": "balanceOf(address)",
|
|
||||||
"313ce567": "decimals()",
|
|
||||||
"06fdde03": "name()",
|
|
||||||
"95d89b41": "symbol()",
|
|
||||||
"18160ddd": "totalSupply()",
|
|
||||||
"a9059cbb": "transfer(address,uint256)",
|
|
||||||
"23b872dd": "transferFrom(address,address,uint256)",
|
|
||||||
"54fd4d50": "version()"
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// var balanceHex = "06fdde03"; // I believe this is the hex for balance
|
|
||||||
// var contractAddress = "0x58cda554935e4a1f2acbe15f8757400af275e084";
|
|
||||||
// var userAddress = "0x5DBB9793537515398A1176d365b636A5321D9e39";
|
|
||||||
// var balanceCall = getDataObj(contractAddress, balanceHex);
|
|
||||||
// var balance = web3.eth.call(balanceCall);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const abiArray = [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"version","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"},{"name":"_extraData","type":"bytes"}],"name":"approveAndCall","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":false,"stateMutability":"nonpayable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}];
|
|
||||||
//const contr = web3.eth.contract(abiArray, '0x58cda554935e4a1f2acbe15f8757400af275e084');
|
|
||||||
const contr = web3.eth.contract(abiArray).at('0x58cda554935e4a1f2acbe15f8757400af275e084');
|
|
||||||
console.log("contr", contr );
|
|
||||||
|
|
||||||
contr.name.call((e,r) => {
|
|
||||||
console.log("nameeeee", e, r)
|
|
||||||
})
|
|
||||||
|
|
||||||
contr.symbol.call((e,r) => {
|
|
||||||
console.log("symboll", e, r)
|
|
||||||
})
|
|
||||||
|
|
||||||
//console.log( const.name )
|
|
||||||
|
|
||||||
// contr.balanceOf('0x98ead4bd2fbbb0cf0b49459aa0510ef53faa6cad', (e, r) => {
|
|
||||||
// console.warn('contrR', e, r.toString(10));
|
|
||||||
// });
|
|
||||||
|
|
||||||
let cntrData = contr.transfer.getData("0x98ead4bd2fbbb0cf0b49459aa0510ef53faa6cad", 1, {
|
|
||||||
from: "0x98ead4bd2fbbb0cf0b49459aa0510ef53faa6cad",
|
|
||||||
gasLimit: 36158,
|
|
||||||
gasPrice: "0x0ee6b28000"
|
|
||||||
})
|
|
||||||
|
|
||||||
console.log("contr", cntrData);
|
|
||||||
// const data = contr.transferFrom(
|
|
||||||
// '0x98ead4bd2fbbb0cf0b49459aa0510ef53faa6cad',
|
|
||||||
// '0x98ead4bd2fbbb0cf0b49459aa0510ef53faa6cad',
|
|
||||||
// 1
|
|
||||||
// );
|
|
||||||
|
|
||||||
// const data = contr.transferFrom(
|
|
||||||
// '0x98ead4bd2fbbb0cf0b49459aa0510ef53faa6cad',
|
|
||||||
// {
|
|
||||||
// from: '0x7314e0f1c0e28474bdb6be3e2c3e0453255188f8',
|
|
||||||
// value: 1
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
|
|
||||||
// const data = contr.transferFrom(
|
|
||||||
// '0x00000000000000000000000098ead4bd2fbbb0cf0b49459aa0510ef53faa6cad',
|
|
||||||
// '0x000000000000000000000000a738ea40b69d87f4f9ac94c9a0763f96248df23b',
|
|
||||||
// 2
|
|
||||||
// );
|
|
||||||
//console.log("contr", contr, data)
|
|
||||||
|
|
||||||
// var addr1 = '0x98ead4bd2fbbb0cf0b49459aa0510ef53faa6cad';
|
|
||||||
// var contractAddr = '0x58cda554935e4a1f2acbe15f8757400af275e084';
|
|
||||||
// var tknAddress = (addr1).substring(2);
|
|
||||||
// var contractData = ('0x70a08231000000000000000000000000' + tknAddress);
|
|
||||||
|
|
||||||
// console.warn("ADDDDDDDD", web3.toHex('0x98ead4bd2fbbb0cf0b49459aa0510ef53faa6cad'));
|
|
||||||
// console.warn("ADDDDDDDD", web3.toHex('98ead4bd2fbbb0cf0b49459aa0510ef53faa6cad'));
|
|
||||||
|
|
||||||
// web3.eth.call({
|
|
||||||
// to: contractAddr,
|
|
||||||
// data: contractData
|
|
||||||
// }, function(err, result) {
|
|
||||||
// if (result) {
|
|
||||||
// console.log("---------result", result, web3);
|
|
||||||
// //var tokens = web3.toBN(result).toString();
|
|
||||||
// //console.log('Tokens Owned: ' + web3.utils.fromWei(tokens, 'ether'));
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// console.log(err); // Dump errors here
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
const pendingBlockFilter = web3.eth.filter('pending');
|
|
||||||
pendingBlockFilter.watch((error, txid) => {
|
|
||||||
//console.warn("Watch pending block", txid, error)
|
|
||||||
if (!error) {
|
|
||||||
|
|
||||||
if (pendingTx.length > 0) {
|
|
||||||
console.error("Watch pending block", pendingTx.indexOf(txid))
|
|
||||||
}
|
|
||||||
|
|
||||||
web3.eth.getTransactionReceipt(txid, async (error, tx) => {
|
|
||||||
if (!error && typeof tx === 'object') {
|
|
||||||
const { addresses } = store.getState().addresses;
|
|
||||||
const receiver = addresses.find(a => a.address === tx.to);
|
|
||||||
if (receiver) {
|
|
||||||
console.error("PendingTX RECV", txid, tx, receiver)
|
|
||||||
const balance = await getBalance(receiver.address);
|
|
||||||
store.dispatch({
|
|
||||||
type: ACTIONS.ADDRESS_SET_BALANCE,
|
|
||||||
txid,
|
|
||||||
address: receiver,
|
|
||||||
balance: web3.fromWei(balance.toString(), 'ether')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const sender = addresses.find(a => a.address === tx.from);
|
|
||||||
if (sender) {
|
|
||||||
const balance = await getBalance(sender.address);
|
|
||||||
store.dispatch({
|
|
||||||
type: ACTIONS.ADDRESS_SET_BALANCE,
|
|
||||||
txid,
|
|
||||||
address: sender,
|
|
||||||
balance: web3.fromWei(balance.toString(), 'ether')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//console.log("PendingTX", txid, tx, receiver, sender)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
//"web3": "^0.19.0"
|
|
||||||
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Web3Service;
|
|
||||||
|
|
||||||
|
|
||||||
export const estimateGas = (gasOptions): Promise<any> => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
web3.eth.estimateGas(gasOptions, (error, result) => {
|
|
||||||
if (error) {
|
|
||||||
reject(error);
|
|
||||||
} else {
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
|
||||||
}
|
|
@ -5,14 +5,10 @@ import RouterService from './RouterService';
|
|||||||
import LocalStorageService from './LocalStorageService';
|
import LocalStorageService from './LocalStorageService';
|
||||||
import CoinmarketcapService from './CoinmarketcapService';
|
import CoinmarketcapService from './CoinmarketcapService';
|
||||||
import TrezorConnectService from './TrezorConnectService';
|
import TrezorConnectService from './TrezorConnectService';
|
||||||
import Web3Service from './Web3Service';
|
|
||||||
import EtherscanService from './EtherscanService';
|
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
RouterService,
|
RouterService,
|
||||||
LocalStorageService,
|
LocalStorageService,
|
||||||
TrezorConnectService,
|
TrezorConnectService,
|
||||||
Web3Service,
|
|
||||||
CoinmarketcapService,
|
CoinmarketcapService,
|
||||||
//EtherscanService,
|
|
||||||
];
|
];
|
@ -9,4 +9,9 @@ export const getAccounts = (accounts: Array<any>, device: any, network: ?string)
|
|||||||
return accounts.filter((addr) => addr.deviceState === device.state);
|
return accounts.filter((addr) => addr.deviceState === device.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public method used in components to find device by state and device_id
|
||||||
|
export const findDevice = (devices: Array<TrezorDevice>, state: ?string, deviceId: ?string, instance: ?string): ?TrezorDevice => {
|
||||||
|
return devices.find(d => d.state === state && d.features && d.features.device_id === deviceId && d.instance === instance);
|
||||||
}
|
}
|
@ -95,6 +95,8 @@ aside {
|
|||||||
margin: 12px 0px 12px 80px;
|
margin: 12px 0px 12px 80px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.device-select {
|
.device-select {
|
||||||
background: @color_white;
|
background: @color_white;
|
||||||
border-bottom: 1px solid @color_divider;
|
border-bottom: 1px solid @color_divider;
|
||||||
@ -246,6 +248,56 @@ aside {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.device-menu {
|
||||||
|
padding: 8px 0px;
|
||||||
|
// padding-left: 80px;
|
||||||
|
padding-left: 74px;
|
||||||
|
border-bottom: 1px solid @color_divider;
|
||||||
|
|
||||||
|
div {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
line-height: 24px;
|
||||||
|
cursor: pointer;
|
||||||
|
color: @color_text_secondary;
|
||||||
|
.hover();
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
.icomoon-refresh;
|
||||||
|
// color: @color_text_secondary;
|
||||||
|
position: relative;
|
||||||
|
font-size: 24px;
|
||||||
|
margin-right: 12px;
|
||||||
|
.hover();
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: @color_text_primary;
|
||||||
|
// &:before {
|
||||||
|
// color: @color_text_primary;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
&.forget {
|
||||||
|
&:before {
|
||||||
|
.icomoon-eject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.clone {
|
||||||
|
&:before {
|
||||||
|
.icomoon-settings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.settings {
|
||||||
|
&:before {
|
||||||
|
.icomoon-settings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: block;
|
display: block;
|
||||||
@ -391,12 +443,12 @@ aside {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.ropsten:before,
|
&.ropsten:before,
|
||||||
&.eth:before {
|
&.ethereum:before {
|
||||||
background-image: url('../images/eth-logo.png');
|
background-image: url('../images/eth-logo.png');
|
||||||
background-size: auto 20px;
|
background-size: auto 20px;
|
||||||
}
|
}
|
||||||
&.rinkeby:before,
|
&.rinkeby:before,
|
||||||
&.etc:before {
|
&.ethereum-classic:before {
|
||||||
background-image: url('../images/etc-logo.png');
|
background-image: url('../images/etc-logo.png');
|
||||||
background-size: auto 20px;
|
background-size: auto 20px;
|
||||||
}
|
}
|
||||||
|
@ -169,5 +169,6 @@
|
|||||||
|
|
||||||
.icomoon-download {
|
.icomoon-download {
|
||||||
.icomoon-base();
|
.icomoon-base();
|
||||||
content: "\e91f";
|
content: "\e91b";
|
||||||
|
transform: rotate(180deg)
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,7 @@
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 36px 0px;
|
padding: 36px 0px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
width: 420px;
|
// width: 420px;
|
||||||
|
|
||||||
p {
|
p {
|
||||||
// flex: 1;
|
// flex: 1;
|
||||||
@ -197,6 +197,18 @@
|
|||||||
// color: @color_green_secondary;
|
// color: @color_green_secondary;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
.webusb-and,
|
||||||
|
.trezor-webusb-button {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.webusb {
|
||||||
|
width: 400px;
|
||||||
|
.webusb-and,
|
||||||
|
.trezor-webusb-button {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
|
@ -108,6 +108,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.duplicate,
|
||||||
.remember {
|
.remember {
|
||||||
width: 360px;
|
width: 360px;
|
||||||
padding: 24px 48px;
|
padding: 24px 48px;
|
||||||
@ -137,6 +138,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.close-modal {
|
.close-modal {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -190,20 +190,23 @@
|
|||||||
|
|
||||||
.advanced-container {
|
.advanced-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 0px 48px;
|
padding: 0px 48px;
|
||||||
|
|
||||||
padding-bottom: 24px;
|
padding-bottom: 24px;
|
||||||
button {
|
button {
|
||||||
width: 50%;
|
min-width: 50%;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
&.opened {
|
&.opened {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
button {
|
button {
|
||||||
position: relative;
|
position: relative;
|
||||||
left: 50%;
|
// left: 50%;
|
||||||
width: 50%;
|
// width: 50%;
|
||||||
|
float: right; // TODO: better
|
||||||
}
|
}
|
||||||
.advanced {
|
.advanced {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@ -231,6 +234,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @media screen and (max-width: 900px) {
|
||||||
|
// :not(.opened) {
|
||||||
|
// border: 1px solid red;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,12 +13,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.ropsten:before,
|
&.ropsten:before,
|
||||||
&.eth:before {
|
&.ethereum:before {
|
||||||
background-image: url('../images/eth-logo.png');
|
background-image: url('../images/eth-logo.png');
|
||||||
background-size: auto 20px;
|
background-size: auto 20px;
|
||||||
}
|
}
|
||||||
&.rinkeby:before,
|
&.rinkeby:before,
|
||||||
&.etc:before {
|
&.ethereum-classic:before {
|
||||||
background-image: url('../images/etc-logo.png');
|
background-image: url('../images/etc-logo.png');
|
||||||
background-size: auto 20px;
|
background-size: auto 20px;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user