mirror of
https://github.com/trezor/trezor-wallet
synced 2025-04-27 12:39:10 +00:00
Flowtype everywhere!
This commit is contained in:
parent
8aeb10cf2c
commit
c597f482dc
@ -1,3 +1,5 @@
|
||||
[include]
|
||||
|
||||
[ignore]
|
||||
.*/node_modules/bitcoinjs-lib-zcash/.*
|
||||
.*/node_modules/bitcoinjs-lib/.*
|
||||
@ -9,7 +11,13 @@
|
||||
.*/src/solidity/.*
|
||||
|
||||
[libs]
|
||||
./src/js/flowtype/redux_v3.x.x.js
|
||||
./src/js/flowtype/react-redux_v5.x.x.js
|
||||
./src/js/flowtype/react-router_v4.x.x.js
|
||||
./src/js/flowtype/react-router-dom_v4.x.x.js
|
||||
./src/js/flowtype/react-router-redux.js
|
||||
./src/js/flowtype/css.js
|
||||
./src/js/flowtype/trezor-connect.js
|
||||
|
||||
|
||||
[options]
|
||||
|
@ -10,6 +10,9 @@
|
||||
"bugs": {
|
||||
"url": "https://github.com/szymonlesisz/trezor-connect-react-boilerplate/issues"
|
||||
},
|
||||
"bin": {
|
||||
"flow": "./node_modules/flow-bin"
|
||||
},
|
||||
"license": "LGPL-3.0+",
|
||||
"scripts": {
|
||||
"dev": "babel-node ./webpack/server.js --connect",
|
||||
@ -48,6 +51,7 @@
|
||||
"redux-logger": "^3.0.6",
|
||||
"redux-raven-middleware": "^1.2.0",
|
||||
"redux-thunk": "^2.2.0",
|
||||
"trezor-connect": "^5.0.10",
|
||||
"web3": "^0.19.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -65,6 +69,7 @@
|
||||
"extract-text-webpack-plugin": "^3.0.0",
|
||||
"file-loader": "^1.1.9",
|
||||
"flow-bin": "^0.69.0",
|
||||
"flow-typed": "^2.4.0",
|
||||
"html-webpack-plugin": "^2.29.0",
|
||||
"json-loader": "^0.5.7",
|
||||
"less": "^3.0.1",
|
||||
|
@ -117,19 +117,6 @@
|
||||
}
|
||||
],
|
||||
|
||||
|
||||
|
||||
|
||||
"bridge": {
|
||||
"url": "https://localback.net:21324",
|
||||
"configUrl": "data/config_signed.bin",
|
||||
"latestUrl": "data/bridge/latest.txt"
|
||||
},
|
||||
"extensionId": "jcjjhjgimijdkoamemaghajlhegmoclj",
|
||||
"storageVersion": "1.1.0",
|
||||
"metadataVersion": "1.0.0",
|
||||
|
||||
|
||||
"supportedBrowsers": {
|
||||
"chrome": {
|
||||
"version": 59,
|
||||
|
@ -5,35 +5,51 @@ import * as ACCOUNT from './constants/account';
|
||||
|
||||
import { initialState } from '../reducers/AbstractAccountReducer';
|
||||
import { findSelectedDevice } from '../reducers/TrezorConnectReducer';
|
||||
import type { State } from '../reducers/AbstractAccountReducer';
|
||||
|
||||
export const init = (): any => {
|
||||
return (dispatch, getState): void => {
|
||||
import type { AsyncAction, Action, GetState, Dispatch, TrezorDevice } from '../flowtype';
|
||||
import type { State } from '../reducers/AbstractAccountReducer';
|
||||
import type { Coin } from '../reducers/LocalStorageReducer';
|
||||
|
||||
export type AbstractAccountAction = {
|
||||
type: typeof ACCOUNT.INIT,
|
||||
state: State
|
||||
} | {
|
||||
type: typeof ACCOUNT.DISPOSE,
|
||||
};
|
||||
|
||||
export const init = (): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
|
||||
const { location } = getState().router;
|
||||
const urlParams = location.params;
|
||||
const urlParams = location.state;
|
||||
|
||||
const selected = findSelectedDevice( getState().connect );
|
||||
const selected: ?TrezorDevice = findSelectedDevice( getState().connect );
|
||||
if (!selected) return;
|
||||
|
||||
const { config } = getState().localStorage;
|
||||
const coin: ?Coin = config.coins.find(c => c.network === urlParams.network);
|
||||
if (!coin) return;
|
||||
|
||||
const state: State = {
|
||||
index: parseInt(urlParams.address),
|
||||
deviceState: selected.state,
|
||||
deviceId: selected.features.device_id,
|
||||
deviceState: selected.state || '0',
|
||||
deviceId: selected.features ? selected.features.device_id : '0',
|
||||
deviceInstance: selected.instance,
|
||||
network: urlParams.network,
|
||||
location: location.pathname
|
||||
coin,
|
||||
location: location.pathname,
|
||||
};
|
||||
|
||||
dispatch({
|
||||
type: ACCOUNT.INIT,
|
||||
state: state
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export const update = (): any => {
|
||||
return (dispatch, getState): void => {
|
||||
export const update = (): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
const {
|
||||
abstractAccount,
|
||||
router
|
||||
@ -46,10 +62,14 @@ export const update = (): any => {
|
||||
}
|
||||
}
|
||||
|
||||
export const dispose = (): any => {
|
||||
return (dispatch, getState): void => {
|
||||
dispatch({
|
||||
type: ACCOUNT.DISPOSE,
|
||||
});
|
||||
export const dispose = (): Action => {
|
||||
return {
|
||||
type: ACCOUNT.DISPOSE
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
init,
|
||||
update,
|
||||
dispose
|
||||
}
|
15
src/js/actions/AddressActions.js
Normal file
15
src/js/actions/AddressActions.js
Normal file
@ -0,0 +1,15 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
import * as ADDRESS from './constants/address';
|
||||
|
||||
export type AddressAction = {
|
||||
type: typeof ADDRESS.CREATE,
|
||||
payload: any
|
||||
} | {
|
||||
type: typeof ADDRESS.SET_BALANCE,
|
||||
payload: any
|
||||
} | {
|
||||
type: typeof ADDRESS.SET_NONCE,
|
||||
payload: any
|
||||
}
|
@ -13,6 +13,16 @@ import HDKey from 'hdkey';
|
||||
import EthereumjsUtil from 'ethereumjs-util';
|
||||
import { getNonceAsync, getBalanceAsync, getTokenBalanceAsync } from './Web3Actions';
|
||||
|
||||
|
||||
|
||||
export type DiscoveryAction = {
|
||||
type: typeof DISCOVERY.START,
|
||||
} | {
|
||||
type: typeof DISCOVERY.STOP,
|
||||
} | {
|
||||
type: typeof DISCOVERY.COMPLETE,
|
||||
};
|
||||
|
||||
export const start = (device: any, network: string, ignoreCompleted?: boolean): any => {
|
||||
return (dispatch, getState) => {
|
||||
|
||||
@ -310,7 +320,7 @@ export const check = (): any => {
|
||||
const selected = findSelectedDevice(getState().connect);
|
||||
if (!selected) return;
|
||||
|
||||
const urlParams = getState().router.location.params;
|
||||
const urlParams = getState().router.location.state;
|
||||
if (urlParams.network) {
|
||||
const discoveryProcess: ?Discovery = getState().discovery.find(d => d.deviceState === selected.state && d.network === urlParams.network);
|
||||
if (!discoveryProcess) {
|
||||
|
@ -1,10 +1,2 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
|
||||
export const onGasPriceChange2 = (gasPrice: string): void => {
|
||||
return {
|
||||
type: '',
|
||||
gasPrice
|
||||
}
|
||||
}
|
@ -6,10 +6,26 @@ import * as ADDRESS from './constants/address';
|
||||
import * as TOKEN from './constants/token';
|
||||
import * as DISCOVERY from './constants/discovery';
|
||||
import * as STORAGE from './constants/localStorage';
|
||||
import { httpRequest } from '../utils/networkUtils';
|
||||
import { JSONRequest, httpRequest } from '../utils/networkUtils';
|
||||
|
||||
export function loadData(): any {
|
||||
return async (dispatch, getState) => {
|
||||
import type { AsyncAction, GetState, Dispatch } from '../flowtype';
|
||||
import type { Config, Coin, TokensCollection } from '../reducers/LocalStorageReducer';
|
||||
|
||||
export type StorageAction = {
|
||||
type: typeof STORAGE.READY,
|
||||
config: any,
|
||||
tokens: any,
|
||||
ERC20Abi: any
|
||||
} | {
|
||||
type: typeof STORAGE.SAVE,
|
||||
network: string,
|
||||
} | {
|
||||
type: typeof STORAGE.ERROR,
|
||||
error: string,
|
||||
};
|
||||
|
||||
export const loadData = (): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
|
||||
// check if local storage is available
|
||||
// let available: boolean = true;
|
||||
@ -27,16 +43,51 @@ export function loadData(): any {
|
||||
}
|
||||
}
|
||||
|
||||
export function loadTokensFromJSON(): any {
|
||||
return async (dispatch, getState) => {
|
||||
// const parseConfig = (json: JSON): Config => {
|
||||
|
||||
// if (json['coins']) {
|
||||
|
||||
// }
|
||||
|
||||
// for (let key in json) {
|
||||
// if (key === 'coins') {
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
// const coins: Array<Object> = json.coins || [];
|
||||
|
||||
// if ("coins" in json){
|
||||
// json.coins
|
||||
// }
|
||||
// if (!json.hasOwnProperty("fiatValueTickers")) throw new Error(`Property "fiatValueTickers" is missing in appConfig.json`);
|
||||
// if (json.config && json.hasOwnProperty('coins') && Array.isArray(json.coins)) {
|
||||
// json.coins.map(c => {
|
||||
// return {
|
||||
|
||||
// }
|
||||
// })
|
||||
// } else {
|
||||
// throw new Error(`Property "coins" is missing in appConfig.json`);
|
||||
// }
|
||||
|
||||
|
||||
// return {
|
||||
// coins: [],
|
||||
// fiatValueTickers: []
|
||||
// }
|
||||
// }
|
||||
|
||||
export function loadTokensFromJSON(): AsyncAction {
|
||||
return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||
try {
|
||||
const config = await httpRequest('data/appConfig.json', 'json');
|
||||
const config: Config = await httpRequest('data/appConfig.json', 'json');
|
||||
const ERC20Abi = await httpRequest('data/ERC20Abi.json', 'json');
|
||||
|
||||
// load tokens
|
||||
const tokens = await config.coins.reduce(async (promise: Promise<any>, coin: any): Promise<any> => {
|
||||
const collection = await promise;
|
||||
const json: JSON = await httpRequest(coin.tokens, 'json');
|
||||
const tokens = await config.coins.reduce(async (promise: Promise<TokensCollection>, coin: Coin): Promise<TokensCollection> => {
|
||||
const collection: TokensCollection = await promise;
|
||||
const json = await httpRequest(coin.tokens, 'json');
|
||||
collection[ coin.network ] = json;
|
||||
return collection;
|
||||
}, Promise.resolve({}));
|
||||
@ -99,8 +150,8 @@ export function loadTokensFromJSON(): any {
|
||||
}
|
||||
|
||||
|
||||
export const save = (key: string, value: string): any => {
|
||||
return (dispatch, getState) => {
|
||||
export const save = (key: string, value: string): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState) => {
|
||||
if (typeof window.localStorage !== 'undefined') {
|
||||
try {
|
||||
window.localStorage.setItem(key, value);
|
||||
|
@ -1,15 +1,25 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
export const toggle = (): any => {
|
||||
return (dispatch, getState) => {
|
||||
import * as LOG from './constants/log';
|
||||
|
||||
import type { AsyncAction, GetState, Dispatch } from '../flowtype';
|
||||
|
||||
export type LogAction = {
|
||||
type: typeof LOG.OPEN,
|
||||
} | {
|
||||
type: typeof LOG.CLOSE,
|
||||
};
|
||||
|
||||
export const toggle = (): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
|
||||
if (!getState().log.opened) {
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: getState().log.opened ? 'log__close' : 'log__open'
|
||||
type: getState().log.opened ? LOG.CLOSE : LOG.OPEN
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -5,16 +5,24 @@ import TrezorConnect, { UI, UI_EVENT } from 'trezor-connect';
|
||||
import * as MODAL from './constants/modal';
|
||||
import * as CONNECT from './constants/TrezorConnect';
|
||||
|
||||
import type { AsyncAction, Action, GetState, Dispatch } from '../flowtype';
|
||||
|
||||
export function onPinSubmit(value: string): any {
|
||||
export type ModalAction = {
|
||||
type: typeof MODAL.CLOSE
|
||||
} | {
|
||||
type: typeof MODAL.REMEMBER,
|
||||
device: any
|
||||
};
|
||||
|
||||
export const onPinSubmit = (value: string): Action => {
|
||||
TrezorConnect.uiResponse({ type: UI.RECEIVE_PIN, payload: value });
|
||||
return {
|
||||
type: MODAL.CLOSE
|
||||
}
|
||||
}
|
||||
|
||||
export function onPassphraseSubmit(passphrase: string): any {
|
||||
return async (dispatch, getState): Promise<void> => {
|
||||
export const onPassphraseSubmit = (passphrase: string): AsyncAction => {
|
||||
return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||
const resp = await TrezorConnect.uiResponse({
|
||||
type: UI.RECEIVE_PASSPHRASE,
|
||||
payload: {
|
||||
@ -29,42 +37,42 @@ export function onPassphraseSubmit(passphrase: string): any {
|
||||
}
|
||||
}
|
||||
|
||||
export const askForRemember = (device: any) => {
|
||||
export const askForRemember = (device: any): Action => {
|
||||
return {
|
||||
type: MODAL.REMEMBER,
|
||||
device
|
||||
}
|
||||
}
|
||||
|
||||
export const onRememberDevice = (device: any) => {
|
||||
export const onRememberDevice = (device: any): Action => {
|
||||
return {
|
||||
type: CONNECT.REMEMBER,
|
||||
device
|
||||
}
|
||||
}
|
||||
|
||||
export const onForgetDevice = (device: any) => {
|
||||
export const onForgetDevice = (device: any): Action => {
|
||||
return {
|
||||
type: CONNECT.FORGET,
|
||||
device,
|
||||
}
|
||||
}
|
||||
|
||||
export const onForgetSingleDevice = (device: any) => {
|
||||
export const onForgetSingleDevice = (device: any): Action => {
|
||||
return {
|
||||
type: CONNECT.FORGET_SINGLE,
|
||||
device,
|
||||
}
|
||||
}
|
||||
|
||||
export const onCancel = () => {
|
||||
export const onCancel = (): Action => {
|
||||
return {
|
||||
type: MODAL.CLOSE
|
||||
}
|
||||
}
|
||||
|
||||
export const onDuplicateDevice = (device: any): any => {
|
||||
return (dispatch: any, getState: any): void => {
|
||||
export const onDuplicateDevice = (device: any): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
|
||||
dispatch( onCancel() );
|
||||
|
||||
@ -73,4 +81,15 @@ export const onDuplicateDevice = (device: any): any => {
|
||||
device
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
onPinSubmit,
|
||||
onPassphraseSubmit,
|
||||
askForRemember,
|
||||
onRememberDevice,
|
||||
onForgetDevice,
|
||||
onForgetSingleDevice,
|
||||
onCancel,
|
||||
onDuplicateDevice
|
||||
}
|
@ -3,10 +3,33 @@
|
||||
|
||||
import * as NOTIFICATION from './constants/notification';
|
||||
|
||||
import type { AsyncAction, GetState, Dispatch, RouterLocationState } from '../flowtype';
|
||||
|
||||
export type NotificationAction = {
|
||||
type: typeof NOTIFICATION.ADD,
|
||||
payload: {
|
||||
+type: string,
|
||||
+title: string,
|
||||
+message?: string,
|
||||
+cancelable: boolean,
|
||||
actions?: Array<any>
|
||||
}
|
||||
} | {
|
||||
type: typeof NOTIFICATION.CLOSE,
|
||||
payload?: {
|
||||
id?: string;
|
||||
devicePath?: string
|
||||
}
|
||||
}
|
||||
|
||||
export const close = () => {
|
||||
|
||||
}
|
||||
|
||||
|
||||
// called from RouterService
|
||||
export const clear = (currentParams, requestedParams): any => {
|
||||
return async (dispatch, getState) => {
|
||||
export const clear = (currentParams: RouterLocationState, requestedParams: RouterLocationState): AsyncAction => {
|
||||
return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||
// 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) {
|
||||
|
@ -9,9 +9,24 @@ import { initialState } from '../reducers/ReceiveReducer';
|
||||
import type { State } from '../reducers/ReceiveReducer';
|
||||
import { findSelectedDevice } from '../reducers/TrezorConnectReducer';
|
||||
|
||||
import type { TrezorDevice, AsyncAction, Action, GetState, Dispatch } from '../flowtype';
|
||||
|
||||
export const init = (): any => {
|
||||
return (dispatch, getState): void => {
|
||||
export type ReceiveAction = {
|
||||
type: typeof RECEIVE.INIT,
|
||||
state: State
|
||||
} | {
|
||||
type: typeof RECEIVE.DISPOSE,
|
||||
} | {
|
||||
type: typeof RECEIVE.REQUEST_UNVERIFIED,
|
||||
device: TrezorDevice
|
||||
} | {
|
||||
type: typeof RECEIVE.SHOW_ADDRESS
|
||||
} | {
|
||||
type: typeof RECEIVE.SHOW_UNVERIFIED_ADDRESS
|
||||
}
|
||||
|
||||
export const init = (): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
|
||||
const state: State = {
|
||||
...initialState,
|
||||
@ -25,8 +40,8 @@ export const init = (): any => {
|
||||
}
|
||||
|
||||
|
||||
export const update = (newProps: any): any => {
|
||||
return (dispatch, getState): void => {
|
||||
export const update = (): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
const {
|
||||
abstractAccount,
|
||||
router
|
||||
@ -39,20 +54,20 @@ export const update = (newProps: any): any => {
|
||||
}
|
||||
}
|
||||
|
||||
export const dispose = (address: string): any => {
|
||||
export const dispose = (): Action => {
|
||||
return {
|
||||
type: RECEIVE.DISPOSE
|
||||
}
|
||||
}
|
||||
|
||||
export const showUnverifiedAddress = () => {
|
||||
export const showUnverifiedAddress = (): Action => {
|
||||
return {
|
||||
type: RECEIVE.SHOW_UNVERIFIED_ADDRESS
|
||||
}
|
||||
}
|
||||
|
||||
export const showAddress = (address_n: string): any => {
|
||||
return async (dispatch, getState) => {
|
||||
export const showAddress = (address_n: string): AsyncAction => {
|
||||
return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||
|
||||
const selected = findSelectedDevice(getState().connect);
|
||||
if (!selected) return;
|
||||
@ -99,4 +114,12 @@ export const showAddress = (address_n: string): any => {
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
init,
|
||||
update,
|
||||
dispose,
|
||||
showAddress,
|
||||
showUnverifiedAddress
|
||||
}
|
@ -16,12 +16,72 @@ import BigNumber from 'bignumber.js';
|
||||
|
||||
import { initialState } from '../reducers/SendFormReducer';
|
||||
import { findAccount } from '../reducers/AccountsReducer';
|
||||
import type { State, FeeLevel } from '../reducers/SendFormReducer';
|
||||
import type { Account } from '../reducers/AccountsReducer';
|
||||
import { findToken } from '../reducers/TokensReducer';
|
||||
import { findSelectedDevice } from '../reducers/TrezorConnectReducer';
|
||||
|
||||
import type {
|
||||
Dispatch,
|
||||
GetState,
|
||||
Action,
|
||||
AsyncAction,
|
||||
RouterLocationState,
|
||||
TrezorDevice
|
||||
} from '../flowtype';
|
||||
import type { State as AccountState } from '../reducers/AbstractAccountReducer';
|
||||
import type { Web3Instance } from '../reducers/Web3Reducer';
|
||||
import type { Config, Coin } from '../reducers/LocalStorageReducer';
|
||||
import type { Token } from '../reducers/TokensReducer';
|
||||
import type { State, FeeLevel } from '../reducers/SendFormReducer';
|
||||
import type { Account } from '../reducers/AccountsReducer';
|
||||
|
||||
export type SendFormAction = {
|
||||
type: typeof SEND.TX_COMPLETE,
|
||||
} | {
|
||||
type: typeof SEND.INIT,
|
||||
state: State
|
||||
} | {
|
||||
type: typeof SEND.DISPOSE
|
||||
} | {
|
||||
type: typeof SEND.TOGGLE_ADVANCED
|
||||
} | {
|
||||
type: typeof SEND.VALIDATION,
|
||||
errors: {[k: string]: string},
|
||||
warnings: {[k: string]: string},
|
||||
infos: {[k: string]: string}
|
||||
} | {
|
||||
type: typeof SEND.ADDRESS_CHANGE,
|
||||
state: State
|
||||
} | {
|
||||
type: typeof SEND.AMOUNT_CHANGE,
|
||||
state: State
|
||||
} | {
|
||||
type: typeof SEND.CURRENCY_CHANGE,
|
||||
state: State
|
||||
} | {
|
||||
type: typeof SEND.SET_MAX,
|
||||
state: State
|
||||
} | {
|
||||
type: typeof SEND.FEE_LEVEL_CHANGE,
|
||||
state: State
|
||||
} | {
|
||||
type: typeof SEND.UPDATE_FEE_LEVELS,
|
||||
state: State
|
||||
} | {
|
||||
type: typeof SEND.FEE_LEVEL_CHANGE,
|
||||
state: State
|
||||
} | {
|
||||
type: typeof SEND.GAS_PRICE_CHANGE,
|
||||
state: State
|
||||
} | {
|
||||
type: typeof SEND.GAS_LIMIT_CHANGE,
|
||||
state: State
|
||||
} | {
|
||||
type: typeof SEND.DATA_CHANGE,
|
||||
state: State
|
||||
};
|
||||
|
||||
//const numberRegExp = new RegExp('^([0-9]{0,10}\\.)?[0-9]{1,18}$');
|
||||
const numberRegExp = new RegExp('^(0|0\\.([0-9]+)?|[1-9]+\\.?([0-9]+)?|\\.[0-9]+)$');
|
||||
const numberRegExp: RegExp = new RegExp('^(0|0\\.([0-9]+)?|[1-9]+\\.?([0-9]+)?|\\.[0-9]+)$');
|
||||
|
||||
const calculateFee = (gasPrice: string, gasLimit: string): string => {
|
||||
return EthereumjsUnits.convert( new BigNumber(gasPrice).times(gasLimit), 'gwei', 'ether');
|
||||
@ -82,38 +142,43 @@ export const getFeeLevels = (symbol: string, gasPrice: BigNumber | string, gasLi
|
||||
]
|
||||
}
|
||||
|
||||
export const findBalance = (getState: any): string => {
|
||||
const accountState = getState().abstractAccount;
|
||||
const { token } = getState().sendForm;
|
||||
const account: ?Account = findAccount(getState().accounts, accountState.index, accountState.deviceState, accountState.network);
|
||||
// export const findBalance = (getState: GetState): string => {
|
||||
// const accountState = getState().abstractAccount;
|
||||
// const { token } = getState().sendForm;
|
||||
// const account: ?Account = findAccount(getState().accounts, accountState.index, accountState.deviceState, accountState.network);
|
||||
|
||||
if (token !== state.network) {
|
||||
return getState().tokens.find(t => t.ethAddress === account.address && t.symbol === token).balance;
|
||||
} else {
|
||||
return account.balance;
|
||||
}
|
||||
}
|
||||
// if (token !== state.network) {
|
||||
// return getState().tokens.find(t => t.ethAddress === account.address && t.symbol === token).balance;
|
||||
// } else {
|
||||
// return account.balance;
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// initialize component
|
||||
export const init = (): any => {
|
||||
return (dispatch, getState): void => {
|
||||
export const init = (): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
|
||||
const accountState: AccountState = getState().abstractAccount;
|
||||
|
||||
const { location } = getState().router;
|
||||
const urlParams = location.params;
|
||||
const urlParams: RouterLocationState = location.state;
|
||||
|
||||
const selected = findSelectedDevice( getState().connect );
|
||||
const selected: ?TrezorDevice = findSelectedDevice( getState().connect );
|
||||
if (!selected) return;
|
||||
|
||||
const web3instance = getState().web3.find(w3 => w3.network === urlParams.network);
|
||||
const web3instance: ?Web3Instance = getState().web3.find(w3 => w3.network === urlParams.network);
|
||||
if (!web3instance) {
|
||||
// no backend for this network
|
||||
//return;
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: check if there are some unfinished tx in localStorage
|
||||
const { config } = getState().localStorage;
|
||||
const coin = config.coins.find(c => c.network === urlParams.network);
|
||||
if (!config) return;
|
||||
|
||||
const coin: ?Coin = config.coins.find(c => c.network === urlParams.network);
|
||||
if (!coin) return;
|
||||
|
||||
const gasPrice: BigNumber = new BigNumber( EthereumjsUnits.convert(web3instance.gasPrice, 'wei', 'gwei') ) || new BigNumber(coin.defaultGasPrice);
|
||||
const gasLimit: string = coin.defaultGasLimit.toString();
|
||||
@ -123,9 +188,9 @@ export const init = (): any => {
|
||||
|
||||
const state: State = {
|
||||
...initialState,
|
||||
network: coin.network,
|
||||
coinSymbol: coin.symbol,
|
||||
token: coin.network,
|
||||
|
||||
feeLevels,
|
||||
selectedFeeLevel: feeLevels.find(f => f.value === 'Normal'),
|
||||
recommendedGasPrice: gasPrice.toString(),
|
||||
@ -141,8 +206,8 @@ export const init = (): any => {
|
||||
}
|
||||
}
|
||||
|
||||
export const update = (): any => {
|
||||
return (dispatch, getState): void => {
|
||||
export const update = (): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
const {
|
||||
abstractAccount,
|
||||
router
|
||||
@ -156,29 +221,29 @@ export const update = (): any => {
|
||||
}
|
||||
}
|
||||
|
||||
export const dispose = (): any => {
|
||||
export const dispose = (): Action => {
|
||||
return {
|
||||
type: SEND.DISPOSE
|
||||
}
|
||||
}
|
||||
|
||||
export const toggleAdvanced = (address: string): any => {
|
||||
export const toggleAdvanced = (address: string): Action => {
|
||||
return {
|
||||
type: SEND.TOGGLE_ADVANCED
|
||||
}
|
||||
}
|
||||
|
||||
export const validation = (): any => {
|
||||
return (dispatch, getState): void => {
|
||||
export const validation = (): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
|
||||
const accountState = getState().abstractAccount;
|
||||
const accountState: AccountState = getState().abstractAccount;
|
||||
const state: State = getState().sendForm;
|
||||
|
||||
const errors: {[k: string]: string} = {};
|
||||
const warnings: {[k: string]: string} = {};
|
||||
const infos: {[k: string]: string} = {};
|
||||
|
||||
if (!state.untouched) {
|
||||
|
||||
// valid address
|
||||
if (state.touched.address) {
|
||||
|
||||
@ -208,8 +273,11 @@ export const validation = (): any => {
|
||||
} else if (state.amount.length > 0 && !state.amount.match(numberRegExp)) {
|
||||
errors.amount = 'Amount is not a number';
|
||||
} else {
|
||||
|
||||
const account: ?Account = findAccount(getState().accounts, accountState.index, accountState.deviceState, accountState.network);
|
||||
let decimalRegExp;
|
||||
if (!account) return; // this should not happen
|
||||
|
||||
let decimalRegExp: RegExp;
|
||||
|
||||
if (state.token !== accountState.network) {
|
||||
const token: any = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === state.token);
|
||||
@ -296,8 +364,8 @@ export const validation = (): any => {
|
||||
}
|
||||
|
||||
|
||||
export const onAddressChange = (address: string): any => {
|
||||
return (dispatch, getState): void => {
|
||||
export const onAddressChange = (address: string): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
|
||||
const currentState: State = getState().sendForm;
|
||||
const touched = { ...currentState.touched };
|
||||
@ -318,10 +386,10 @@ export const onAddressChange = (address: string): any => {
|
||||
}
|
||||
}
|
||||
|
||||
export const onAmountChange = (amount: string): any => {
|
||||
return (dispatch, getState): void => {
|
||||
export const onAmountChange = (amount: string): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
|
||||
const accountState = getState().abstractAccount;
|
||||
const accountState: AccountState = getState().abstractAccount;
|
||||
const currentState: State = getState().sendForm;
|
||||
const isToken: boolean = currentState.token !== accountState.network;
|
||||
const touched = { ...currentState.touched };
|
||||
@ -345,11 +413,10 @@ export const onAmountChange = (amount: string): any => {
|
||||
}
|
||||
}
|
||||
|
||||
export const onCurrencyChange = (currency: any): any => {
|
||||
|
||||
return (dispatch, getState): void => {
|
||||
const accountState = getState().abstractAccount;
|
||||
const currentState = getState().sendForm;
|
||||
export const onCurrencyChange = (currency: any): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
const accountState: AccountState = getState().abstractAccount;
|
||||
const currentState: State = getState().sendForm;
|
||||
const isToken: boolean = currency.value !== accountState.network;
|
||||
|
||||
const account: ?Account = findAccount(getState().accounts, accountState.index, accountState.deviceState, accountState.network);
|
||||
@ -359,7 +426,9 @@ export const onCurrencyChange = (currency: any): any => {
|
||||
}
|
||||
|
||||
const { config } = getState().localStorage;
|
||||
const coin = config.coins.find(c => c.network === accountState.network);
|
||||
if (!config) return;
|
||||
const coin: ?Coin = config.coins.find(c => c.network === accountState.network);
|
||||
if (!coin) return;
|
||||
|
||||
let gasLimit: string = '';
|
||||
let amount: string = currentState.amount;
|
||||
@ -368,8 +437,9 @@ export const onCurrencyChange = (currency: any): any => {
|
||||
if (isToken) {
|
||||
gasLimit = coin.defaultGasLimitTokens.toString();
|
||||
if (currentState.setMax) {
|
||||
const tokenBalance: string = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === currency.value).balance;
|
||||
amount = tokenBalance;
|
||||
const token: ?Token = findToken(getState().tokens, account.address, currentState.token, accountState.deviceState);
|
||||
if (!token) return;
|
||||
amount = token.balance;
|
||||
}
|
||||
total = calculateTotal('0', currentState.gasPrice, currentState.gasLimit);
|
||||
} else {
|
||||
@ -381,6 +451,8 @@ export const onCurrencyChange = (currency: any): any => {
|
||||
}
|
||||
|
||||
const feeLevels: Array<FeeLevel> = getFeeLevels(currentState.coinSymbol, currentState.gasPrice, gasLimit);
|
||||
const selectedFeeLevel: ?FeeLevel = feeLevels.find(f => f.value === currentState.selectedFeeLevel.value);
|
||||
if (!selectedFeeLevel) return;
|
||||
|
||||
const state: State = {
|
||||
...currentState,
|
||||
@ -388,7 +460,7 @@ export const onCurrencyChange = (currency: any): any => {
|
||||
amount,
|
||||
total,
|
||||
feeLevels,
|
||||
selectedFeeLevel: feeLevels.find(f => f.value === currentState.selectedFeeLevel.value),
|
||||
selectedFeeLevel,
|
||||
gasLimit,
|
||||
};
|
||||
|
||||
@ -402,10 +474,10 @@ export const onCurrencyChange = (currency: any): any => {
|
||||
|
||||
|
||||
|
||||
export const onSetMax = (): any => {
|
||||
return (dispatch, getState): void => {
|
||||
const accountState = getState().abstractAccount;
|
||||
const currentState = getState().sendForm;
|
||||
export const onSetMax = (): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
const accountState: AccountState = getState().abstractAccount;
|
||||
const currentState: State = getState().sendForm;
|
||||
const isToken: boolean = currentState.token !== accountState.network;
|
||||
const touched = { ...currentState.touched };
|
||||
touched.amount = true;
|
||||
@ -420,8 +492,9 @@ export const onSetMax = (): any => {
|
||||
let total: string = currentState.total;
|
||||
if (!currentState.setMax) {
|
||||
if (isToken) {
|
||||
const tokenBalance: string = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === currentState.token).balance;
|
||||
amount = tokenBalance;
|
||||
const token: ?Token = findToken(getState().tokens, account.address, currentState.token, accountState.deviceState);
|
||||
if (!token) return;
|
||||
amount = token.balance;
|
||||
total = calculateTotal('0', currentState.gasPrice, currentState.gasLimit);
|
||||
} else {
|
||||
amount = calculateMaxAmount(account.balance, currentState.gasPrice, currentState.gasLimit);
|
||||
@ -446,12 +519,17 @@ export const onSetMax = (): any => {
|
||||
}
|
||||
}
|
||||
|
||||
export const onFeeLevelChange = (feeLevel: any): any => {
|
||||
return (dispatch, getState): void => {
|
||||
const accountState = getState().abstractAccount;
|
||||
const currentState = getState().sendForm;
|
||||
export const onFeeLevelChange = (feeLevel: FeeLevel): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
const accountState: AccountState = getState().abstractAccount;
|
||||
const currentState: State = getState().sendForm;
|
||||
const isToken: boolean = currentState.token !== accountState.network;
|
||||
|
||||
const { config } = getState().localStorage;
|
||||
if (!config) return;
|
||||
const coin: ?Coin = config.coins.find(c => c.network === accountState.network);
|
||||
if (!coin) return;
|
||||
|
||||
const state: State = {
|
||||
...currentState,
|
||||
untouched: false,
|
||||
@ -464,16 +542,22 @@ export const onFeeLevelChange = (feeLevel: any): any => {
|
||||
feeLevel.gasPrice = state.gasPrice;
|
||||
feeLevel.label = `${ calculateFee(state.gasPrice, state.gasLimit) } ${ state.coinSymbol }`;
|
||||
} else {
|
||||
const customLevel = state.feeLevels.find(f => f.value === 'Custom');
|
||||
customLevel.label = '';
|
||||
const customLevel: ?FeeLevel = state.feeLevels.find(f => f.value === 'Custom');
|
||||
if (customLevel)
|
||||
customLevel.label = '';
|
||||
state.gasPrice = feeLevel.gasPrice;
|
||||
state.gasLimit = isToken ? coin.defaultGasLimitTokens.toString() : coin.defaultGasLimit.toString();
|
||||
// reset custom gasLimit
|
||||
}
|
||||
|
||||
if (currentState.setMax) {
|
||||
const account: ?Account = findAccount(getState().accounts, accountState.index, accountState.deviceState, accountState.network);
|
||||
if (!account) return;
|
||||
|
||||
if (isToken) {
|
||||
const tokenBalance: string = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === currentState.token).balance;
|
||||
state.amount = tokenBalance;
|
||||
const token: ?Token = findToken(getState().tokens, account.address, currentState.token, accountState.deviceState);
|
||||
if (!token) return;
|
||||
state.amount = token.balance;
|
||||
} else {
|
||||
state.amount = calculateMaxAmount(account.balance, state.gasPrice, state.gasLimit);
|
||||
}
|
||||
@ -488,14 +572,16 @@ export const onFeeLevelChange = (feeLevel: any): any => {
|
||||
}
|
||||
}
|
||||
|
||||
export const updateFeeLevels = (): any => {
|
||||
return (dispatch, getState): void => {
|
||||
const accountState = getState().abstractAccount;
|
||||
const currentState = getState().sendForm;
|
||||
export const updateFeeLevels = (): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
const accountState: AccountState = getState().abstractAccount;
|
||||
const currentState: State = getState().sendForm;
|
||||
const isToken: boolean = currentState.token !== accountState.network;
|
||||
|
||||
const feeLevels: Array<FeeLevel> = getFeeLevels(currentState.coinSymbol, currentState.recommendedGasPrice, currentState.gasLimit);
|
||||
const selectedFeeLevel: ?FeeLevel = feeLevels.find(f => f.value === currentState.selectedFeeLevel.value)
|
||||
const selectedFeeLevel: ?FeeLevel = feeLevels.find(f => f.value === currentState.selectedFeeLevel.value);
|
||||
if (!selectedFeeLevel) return;
|
||||
|
||||
const state: State = {
|
||||
...currentState,
|
||||
feeLevels,
|
||||
@ -507,8 +593,11 @@ export const updateFeeLevels = (): any => {
|
||||
|
||||
if (currentState.setMax) {
|
||||
const account: ?Account = findAccount(getState().accounts, accountState.index, accountState.deviceState, accountState.network);
|
||||
if (!account) return;
|
||||
if (isToken) {
|
||||
const tokenBalance: string = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === currentState.token).balance;
|
||||
const token: ?Token = findToken(getState().tokens, account.address, state.token, accountState.deviceState);
|
||||
if (!token) return;
|
||||
const tokenBalance: string = token.balance;
|
||||
state.amount = tokenBalance;
|
||||
} else {
|
||||
state.amount = calculateMaxAmount(account.balance, state.gasPrice, state.gasLimit);
|
||||
@ -524,10 +613,10 @@ export const updateFeeLevels = (): any => {
|
||||
}
|
||||
}
|
||||
|
||||
export const onGasPriceChange = (gasPrice: string): any => {
|
||||
return (dispatch, getState): void => {
|
||||
const accountState = getState().abstractAccount;
|
||||
const currentState = getState().sendForm;
|
||||
export const onGasPriceChange = (gasPrice: string): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
const accountState: AccountState = getState().abstractAccount;
|
||||
const currentState: State = getState().sendForm;
|
||||
const isToken: boolean = currentState.token !== accountState.network;
|
||||
|
||||
const touched = { ...currentState.touched };
|
||||
@ -542,6 +631,7 @@ export const onGasPriceChange = (gasPrice: string): any => {
|
||||
|
||||
if (gasPrice.match(numberRegExp) && state.gasLimit.match(numberRegExp)) {
|
||||
const customLevel = currentState.feeLevels.find(f => f.value === 'Custom');
|
||||
if (!customLevel) return;
|
||||
customLevel.gasPrice = gasPrice;
|
||||
customLevel.label = `${ calculateFee(gasPrice, state.gasLimit) } ${ state.coinSymbol }`;
|
||||
|
||||
@ -549,8 +639,11 @@ export const onGasPriceChange = (gasPrice: string): any => {
|
||||
|
||||
if (currentState.setMax) {
|
||||
const account: ?Account = findAccount(getState().accounts, accountState.index, accountState.deviceState, accountState.network);
|
||||
if (!account) return;
|
||||
if (isToken) {
|
||||
const tokenBalance: string = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === currentState.token).balance;
|
||||
const token: ?Token = findToken(getState().tokens, account.address, state.token, accountState.deviceState);
|
||||
if (!token) return;
|
||||
const tokenBalance: string = token.balance;
|
||||
state.amount = tokenBalance;
|
||||
} else {
|
||||
state.amount = calculateMaxAmount(account.balance, state.gasPrice, state.gasLimit);
|
||||
@ -568,10 +661,10 @@ export const onGasPriceChange = (gasPrice: string): any => {
|
||||
}
|
||||
}
|
||||
|
||||
export const onGasLimitChange = (gasLimit: string): any => {
|
||||
return (dispatch, getState): void => {
|
||||
const accountState = getState().abstractAccount;
|
||||
const currentState = getState().sendForm;
|
||||
export const onGasLimitChange = (gasLimit: string): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
const accountState: AccountState = getState().abstractAccount;
|
||||
const currentState: State = getState().sendForm;
|
||||
const isToken: boolean = currentState.token !== accountState.network;
|
||||
|
||||
const touched = { ...currentState.touched };
|
||||
@ -585,15 +678,20 @@ export const onGasLimitChange = (gasLimit: string): any => {
|
||||
};
|
||||
|
||||
if (gasLimit.match(numberRegExp) && state.gasPrice.match(numberRegExp)) {
|
||||
const customLevel = state.feeLevels.find(f => f.value === 'Custom');
|
||||
const customLevel: ?FeeLevel = state.feeLevels.find(f => f.value === 'Custom');
|
||||
if (!customLevel) return;
|
||||
customLevel.label = `${ calculateFee(currentState.gasPrice, gasLimit) } ${ state.coinSymbol }`;
|
||||
|
||||
state.selectedFeeLevel = customLevel;
|
||||
|
||||
if (state.setMax) {
|
||||
const account: ?Account = findAccount(getState().accounts, accountState.index, accountState.deviceState, accountState.network);
|
||||
if (!account) return;
|
||||
|
||||
if (isToken) {
|
||||
const tokenBalance: string = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === state.token).balance;
|
||||
const token: ?Token = findToken(getState().tokens, account.address, state.token, accountState.deviceState);
|
||||
if (!token) return;
|
||||
const tokenBalance: string = token.balance;
|
||||
state.amount = tokenBalance;
|
||||
} else {
|
||||
state.amount = calculateMaxAmount(account.balance, state.gasPrice, state.gasLimit);
|
||||
@ -611,9 +709,9 @@ export const onGasLimitChange = (gasLimit: string): any => {
|
||||
}
|
||||
}
|
||||
|
||||
export const onDataChange = (data: string): any => {
|
||||
return (dispatch, getState): void => {
|
||||
const currentState = getState().sendForm;
|
||||
export const onDataChange = (data: string): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
const currentState: State = getState().sendForm;
|
||||
const touched = { ...currentState.touched };
|
||||
touched.data = true;
|
||||
|
||||
@ -632,33 +730,37 @@ export const onDataChange = (data: string): any => {
|
||||
}
|
||||
}
|
||||
|
||||
export const onSend = (): any => {
|
||||
export const onSend = (): AsyncAction => {
|
||||
//return onSendERC20();
|
||||
return async (dispatch: Dispatch, getState: GetState): Promise<any> => {
|
||||
|
||||
return async (dispatch, getState): Promise<any> => {
|
||||
|
||||
const accountState = getState().abstractAccount;
|
||||
const accountState: AccountState = getState().abstractAccount;
|
||||
const currentState: State = getState().sendForm;
|
||||
const web3instance = getState().web3.filter(w3 => w3.network === accountState.network)[0];
|
||||
const web3 = web3instance.web3;
|
||||
const web3instance: ?Web3Instance = getState().web3.filter(w3 => w3.network === accountState.network)[0];
|
||||
const account: ?Account = findAccount(getState().accounts, accountState.index, accountState.deviceState, accountState.network);
|
||||
if (!account || !web3instance) return;
|
||||
|
||||
const isToken: boolean = currentState.token !== accountState.network;
|
||||
const web3 = web3instance.web3;
|
||||
|
||||
const address_n = account.addressPath;
|
||||
|
||||
let data: string = '';
|
||||
let txAmount = web3.toHex(web3.toWei(currentState.amount, 'ether'));
|
||||
let txAddress = currentState.address;
|
||||
let txAmount: string = web3.toHex(web3.toWei(currentState.amount, 'ether'));
|
||||
let txAddress: string = currentState.address;
|
||||
if (isToken) {
|
||||
const t = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === currentState.token);
|
||||
const contract = web3instance.erc20.at(t.address);
|
||||
// const t = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === currentState.token);
|
||||
const token: ?Token = findToken(getState().tokens, account.address, currentState.token, accountState.deviceState);
|
||||
if (!token) return;
|
||||
|
||||
const contract = web3instance.erc20.at(token.address);
|
||||
data = contract.transfer.getData(currentState.address, currentState.amount, {
|
||||
from: account.address,
|
||||
gasLimit: currentState.gasLimit,
|
||||
gasPrice: currentState.gasPrice
|
||||
});
|
||||
txAmount = '0x00';
|
||||
txAddress = t.address;
|
||||
txAddress = token.address;
|
||||
}
|
||||
|
||||
const txData = {
|
||||
@ -693,7 +795,7 @@ export const onSend = (): any => {
|
||||
|
||||
// console.log("---->GASSS", txData, gasLimit, gasPrice, EthereumjsUnits.convert(gasPrice, 'gwei', 'wei'));
|
||||
|
||||
const selected = findSelectedDevice(getState().connect);
|
||||
const selected: ?TrezorDevice = findSelectedDevice(getState().connect);
|
||||
if (!selected) return;
|
||||
|
||||
let signedTransaction = await TrezorConnect.ethereumSignTransaction({
|
||||
@ -736,7 +838,9 @@ export const onSend = (): any => {
|
||||
// console.log("---->GASSS", txData, gasLimit2.toString() );
|
||||
|
||||
const { config } = getState().localStorage;
|
||||
const selectedCoin = config.coins.find(c => c.network === currentState.network);
|
||||
if (!config) return;
|
||||
const selectedCoin: ?Coin = config.coins.find(c => c.network === currentState.network);
|
||||
if (!selectedCoin) return;
|
||||
|
||||
try {
|
||||
const tx = new EthereumjsTx(txData);
|
||||
@ -778,3 +882,21 @@ export const onSend = (): any => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
init,
|
||||
update,
|
||||
dispose,
|
||||
|
||||
toggleAdvanced,
|
||||
onAddressChange,
|
||||
onAmountChange,
|
||||
onCurrencyChange,
|
||||
onSetMax,
|
||||
onFeeLevelChange,
|
||||
updateFeeLevels,
|
||||
onGasPriceChange,
|
||||
onGasLimitChange,
|
||||
onDataChange,
|
||||
onSend,
|
||||
}
|
||||
|
@ -7,14 +7,24 @@ import * as TOKEN from './constants/token';
|
||||
import * as ADDRESS from './constants/address';
|
||||
import { resolveAfter } from '../utils/promiseUtils';
|
||||
import { getTokenInfoAsync, getTokenBalanceAsync } from './Web3Actions';
|
||||
|
||||
import { initialState } from '../reducers/SummaryReducer';
|
||||
import type { State } from '../reducers/SummaryReducer';
|
||||
import { findSelectedDevice } from '../reducers/TrezorConnectReducer';
|
||||
|
||||
import type { AsyncAction, Action, GetState, Dispatch } from '../flowtype';
|
||||
import type { State } from '../reducers/SummaryReducer';
|
||||
import type { Token } from '../reducers/TokensReducer';
|
||||
|
||||
export const init = (): any => {
|
||||
return (dispatch, getState): void => {
|
||||
export type SummaryAction = {
|
||||
type: typeof SUMMARY.INIT,
|
||||
state: State
|
||||
} | {
|
||||
type: typeof SUMMARY.DISPOSE,
|
||||
} | {
|
||||
type: typeof SUMMARY.DETAILS_TOGGLE
|
||||
}
|
||||
|
||||
export const init = (): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
|
||||
const state: State = {
|
||||
...initialState,
|
||||
@ -28,8 +38,8 @@ export const init = (): any => {
|
||||
}
|
||||
|
||||
|
||||
export const update = (newProps: any): any => {
|
||||
return (dispatch, getState): void => {
|
||||
export const update = (): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
const {
|
||||
abstractAccount,
|
||||
router
|
||||
@ -43,87 +53,15 @@ export const update = (newProps: any): any => {
|
||||
}
|
||||
}
|
||||
|
||||
export const dispose = (address: string): any => {
|
||||
export const dispose = (): Action => {
|
||||
return {
|
||||
type: SUMMARY.DISPOSE
|
||||
}
|
||||
}
|
||||
|
||||
export const onDetailsToggle = (): any => {
|
||||
export const onDetailsToggle = (): Action => {
|
||||
return {
|
||||
type: SUMMARY.DETAILS_TOGGLE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export const loadTokens = (input: string, account: any): any => {
|
||||
return async (dispatch, getState): Promise<any> => {
|
||||
|
||||
if (input.length < 1) return null;
|
||||
|
||||
const tokens = getState().localStorage.tokens[ account.network ];
|
||||
const value = input.toLowerCase();
|
||||
const result = tokens.filter(t =>
|
||||
t.symbol.toLowerCase().indexOf(value) >= 0 ||
|
||||
t.address.toLowerCase().indexOf(value) >= 0 ||
|
||||
t.name.toLowerCase().indexOf(value) >= 0
|
||||
);
|
||||
|
||||
if (result.length > 0) {
|
||||
return { options: result };
|
||||
} else {
|
||||
const web3instance = getState().web3.find(w3 => w3.network === account.network);
|
||||
|
||||
const info = await getTokenInfoAsync(web3instance.erc20, input);
|
||||
info.address = input;
|
||||
|
||||
if (info) {
|
||||
return {
|
||||
options: [ info ]
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//await resolveAfter(300000);
|
||||
//await resolveAfter(3000);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export const selectToken = (token: any, account: any): any => {
|
||||
return async (dispatch, getState): Promise<any> => {
|
||||
|
||||
const web3instance = getState().web3.find(w3 => w3.network === account.network);
|
||||
dispatch({
|
||||
type: TOKEN.ADD,
|
||||
payload: {
|
||||
...token,
|
||||
ethAddress: account.address,
|
||||
deviceState: account.deviceState
|
||||
}
|
||||
});
|
||||
|
||||
const tokenBalance = await getTokenBalanceAsync(web3instance.erc20, token.address, account.address);
|
||||
dispatch({
|
||||
type: TOKEN.SET_BALANCE,
|
||||
payload: {
|
||||
ethAddress: account.address,
|
||||
address: token.address,
|
||||
balance: tokenBalance.toString()
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export const removeToken = (token: any): any => {
|
||||
return {
|
||||
type: TOKEN.REMOVE,
|
||||
token
|
||||
}
|
||||
}
|
||||
|
113
src/js/actions/TokenActions.js
Normal file
113
src/js/actions/TokenActions.js
Normal file
@ -0,0 +1,113 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
import * as TOKEN from './constants/token';
|
||||
import { getTokenInfoAsync, getTokenBalanceAsync } from './Web3Actions';
|
||||
|
||||
import type { GetState, AsyncAction, Action } from '../flowtype';
|
||||
import type { State, Token } from '../reducers/TokensReducer';
|
||||
import type { Account } from '../reducers/AccountsReducer';
|
||||
import type { NetworkToken } from '../reducers/LocalStorageReducer';
|
||||
|
||||
export type TokenAction = {
|
||||
type: typeof TOKEN.FROM_STORAGE,
|
||||
payload: State
|
||||
} | {
|
||||
type: typeof TOKEN.ADD,
|
||||
payload: Token
|
||||
} | {
|
||||
type: typeof TOKEN.REMOVE,
|
||||
token: Token
|
||||
} | {
|
||||
type: typeof TOKEN.SET_BALANCE,
|
||||
payload: {
|
||||
ethAddress: string,
|
||||
address: string,
|
||||
}
|
||||
}
|
||||
|
||||
export const setBalance = (web3: any, coinIndex: number = 0): AsyncAction => {
|
||||
return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||
}
|
||||
}
|
||||
|
||||
type SelectOptions = {
|
||||
options?: Array<NetworkToken>
|
||||
}
|
||||
|
||||
|
||||
// action from component <reactSelect>
|
||||
export const load = (input: string, network: string): AsyncAction => {
|
||||
return async (dispatch: Dispatch, getState: GetState): Promise<any> => {
|
||||
|
||||
if (input.length < 1) return;
|
||||
|
||||
const tokens = getState().localStorage.tokens[ network ];
|
||||
const value = input.toLowerCase();
|
||||
const result = tokens.filter(t =>
|
||||
t.symbol.toLowerCase().indexOf(value) >= 0 ||
|
||||
t.address.toLowerCase().indexOf(value) >= 0 ||
|
||||
t.name.toLowerCase().indexOf(value) >= 0
|
||||
);
|
||||
|
||||
if (result.length > 0) {
|
||||
return { options: result };
|
||||
} else {
|
||||
const web3instance = getState().web3.find(w3 => w3.network === network);
|
||||
if (!web3instance) return;
|
||||
|
||||
const info = await getTokenInfoAsync(web3instance.erc20, input);
|
||||
info.address = input;
|
||||
|
||||
if (info) {
|
||||
return {
|
||||
options: [ info ]
|
||||
}
|
||||
}
|
||||
//await resolveAfter(300000);
|
||||
//await resolveAfter(3000);
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
export const add = (token: NetworkToken, account: Account): AsyncAction => {
|
||||
return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||
|
||||
const web3instance = getState().web3.find(w3 => w3.network === account.network);
|
||||
if (!web3instance) return;
|
||||
|
||||
dispatch({
|
||||
type: TOKEN.ADD,
|
||||
payload: {
|
||||
loaded: false,
|
||||
deviceState: account.deviceState,
|
||||
name: token.name,
|
||||
symbol: token.symbol,
|
||||
address: token.address,
|
||||
ethAddress: account.address,
|
||||
decimals: token.decimals,
|
||||
balance: '0'
|
||||
}
|
||||
});
|
||||
|
||||
const tokenBalance = await getTokenBalanceAsync(web3instance.erc20, token.address, account.address);
|
||||
dispatch({
|
||||
type: TOKEN.SET_BALANCE,
|
||||
payload: {
|
||||
ethAddress: account.address,
|
||||
address: token.address,
|
||||
balance: tokenBalance.toString()
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export const remove = (token: Token): Action => {
|
||||
return {
|
||||
type: TOKEN.REMOVE,
|
||||
token
|
||||
}
|
||||
}
|
@ -14,29 +14,107 @@ import { resolveAfter } from '../utils/promiseUtils';
|
||||
import { getAccounts } from '../utils/reducerUtils';
|
||||
import { findSelectedDevice } from '../reducers/TrezorConnectReducer';
|
||||
|
||||
export const init = (): any => {
|
||||
return async (dispatch, getState): Promise<void> => {
|
||||
|
||||
import type {
|
||||
Device,
|
||||
ResponseMessage,
|
||||
DeviceMessage,
|
||||
UiMessage,
|
||||
TransportMessage,
|
||||
DeviceMessageType,
|
||||
TransportMessageType,
|
||||
UiMessageType
|
||||
} from 'trezor-connect';
|
||||
|
||||
import type {
|
||||
Dispatch,
|
||||
GetState,
|
||||
Action,
|
||||
AsyncAction,
|
||||
TrezorDevice,
|
||||
RouterLocationState
|
||||
} from '../flowtype';
|
||||
|
||||
|
||||
export type TrezorConnectAction = {
|
||||
type: typeof CONNECT.INITIALIZATION_ERROR,
|
||||
error: any
|
||||
} | {
|
||||
type: typeof CONNECT.SELECT_DEVICE,
|
||||
payload: ?{
|
||||
id: string,
|
||||
instance: string
|
||||
}
|
||||
} | {
|
||||
type: typeof CONNECT.COIN_CHANGED,
|
||||
payload: {
|
||||
network: string
|
||||
}
|
||||
} | {
|
||||
type: typeof CONNECT.AUTH_DEVICE,
|
||||
device: any
|
||||
} | {
|
||||
type: typeof CONNECT.DUPLICATE,
|
||||
device: any
|
||||
} | {
|
||||
type: typeof CONNECT.REMEMBER_REQUEST,
|
||||
device: any
|
||||
} | {
|
||||
type: typeof CONNECT.DISCONNECT_REQUEST,
|
||||
device: any
|
||||
} | {
|
||||
type: typeof CONNECT.FORGET_REQUEST,
|
||||
device: any
|
||||
} | {
|
||||
type: typeof CONNECT.FORGET,
|
||||
device: any
|
||||
} | {
|
||||
type: typeof CONNECT.FORGET_SINGLE,
|
||||
device: any
|
||||
} | {
|
||||
type: typeof CONNECT.REMEMBER,
|
||||
device: any
|
||||
} | {
|
||||
type: typeof CONNECT.TRY_TO_DUPLICATE,
|
||||
device: any
|
||||
} | {
|
||||
type: typeof CONNECT.DEVICE_FROM_STORAGE,
|
||||
payload: Array<any>
|
||||
} | {
|
||||
type: typeof CONNECT.START_ACQUIRING,
|
||||
device: any
|
||||
} | {
|
||||
type: typeof CONNECT.STOP_ACQUIRING,
|
||||
device: any
|
||||
};
|
||||
|
||||
|
||||
export const init = (): AsyncAction => {
|
||||
return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||
// set listeners
|
||||
TrezorConnect.on(DEVICE_EVENT, (event: DeviceMessage): void => {
|
||||
// post event to reducers
|
||||
const type: DeviceMessageType = event.type; // assert flow type
|
||||
dispatch({
|
||||
type: event.type,
|
||||
type,
|
||||
device: event.payload
|
||||
});
|
||||
});
|
||||
|
||||
const version: Object = TrezorConnect.getVersion();
|
||||
TrezorConnect.on(UI_EVENT, (event: UiMessage): void => {
|
||||
// post event to reducers
|
||||
const type: UiMessageType = event.type; // assert flow type
|
||||
dispatch({
|
||||
type: event.type,
|
||||
type,
|
||||
payload: event.payload
|
||||
});
|
||||
});
|
||||
|
||||
TrezorConnect.on(TRANSPORT_EVENT, (event: UiMessage): void => {
|
||||
TrezorConnect.on(TRANSPORT_EVENT, (event: TransportMessage): void => {
|
||||
// post event to reducers
|
||||
const type: TransportMessageType = event.type; // assert flow type
|
||||
dispatch({
|
||||
type: event.type,
|
||||
type,
|
||||
payload: event.payload
|
||||
});
|
||||
});
|
||||
@ -47,7 +125,7 @@ export const init = (): any => {
|
||||
connectSrc: 'https://localhost:8088/',
|
||||
// connectSrc: 'https://connect.trezor.io/tpm/',
|
||||
// connectSrc: 'https://sisyfos.trezor.io/',
|
||||
debug: true,
|
||||
debug: false,
|
||||
popup: false,
|
||||
webusb: true
|
||||
});
|
||||
@ -62,10 +140,10 @@ export const init = (): any => {
|
||||
|
||||
// called after backend was initialized
|
||||
// set listeners for connect/disconnect
|
||||
export const postInit = (): any => {
|
||||
return (dispatch, getState): void => {
|
||||
export const postInit = (): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
|
||||
const handleDeviceConnect = (device) => {
|
||||
const handleDeviceConnect = (device: Device) => {
|
||||
dispatch( initConnectedDevice(device) );
|
||||
}
|
||||
|
||||
@ -75,9 +153,11 @@ export const postInit = (): any => {
|
||||
TrezorConnect.on(DEVICE.CONNECT, handleDeviceConnect);
|
||||
TrezorConnect.on(DEVICE.CONNECT_UNACQUIRED, handleDeviceConnect);
|
||||
|
||||
const { devices } = getState().connect;
|
||||
// const devices: Array<TrezorDevice> = getState().connect.devices;
|
||||
const devices: Array<TrezorDevice> = getState().connect.devices;
|
||||
|
||||
const { initialPathname, initialParams } = getState().wallet;
|
||||
|
||||
const { initialPathname, initialParams } = getState().wallet
|
||||
if (initialPathname) {
|
||||
dispatch({
|
||||
type: WALLET.SET_INITIAL_URL,
|
||||
@ -87,7 +167,7 @@ export const postInit = (): any => {
|
||||
}
|
||||
|
||||
if (devices.length > 0) {
|
||||
const unacquired = devices.find(d => d.unacquired);
|
||||
const unacquired: ?TrezorDevice = devices.find(d => d.unacquired);
|
||||
if (unacquired) {
|
||||
dispatch( onSelectDevice(unacquired) );
|
||||
} else {
|
||||
@ -118,8 +198,8 @@ const sortDevices = (devices: Array<TrezorDevice>): Array<TrezorDevice> => {
|
||||
});
|
||||
}
|
||||
|
||||
export const initConnectedDevice = (device: any, force): any => {
|
||||
return (dispatch, getState): void => {
|
||||
export const initConnectedDevice = (device: any): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
|
||||
const selected = findSelectedDevice(getState().connect);
|
||||
if (!selected || (selected && selected.state)) {
|
||||
@ -137,27 +217,26 @@ export const initConnectedDevice = (device: any, force): any => {
|
||||
// after device_connect event
|
||||
// or after acquiring device
|
||||
// device type could be local TrezorDevice or Device (from trezor-connect device_connect event)
|
||||
export const onSelectDevice = (device: any): any => {
|
||||
return (dispatch, getState): void => {
|
||||
export const onSelectDevice = (device: TrezorDevice | Device): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
// || device.isUsedElsewhere
|
||||
|
||||
console.log("------> REDITTO", device, getState().wallet.initialUrl);
|
||||
|
||||
// switch to initial url and reset this value
|
||||
|
||||
|
||||
if (device.unacquired) {
|
||||
if (!device.features) {
|
||||
dispatch( push(`/device/${ device.path }/acquire`) );
|
||||
} else if (device.features.bootloader_mode) {
|
||||
dispatch( push(`/device/${ device.path }/bootloader`) );
|
||||
} else if (device.instance) {
|
||||
} else if (typeof device.instance === 'number') {
|
||||
dispatch( push(`/device/${ device.features.device_id }:${ device.instance }`) );
|
||||
} else {
|
||||
|
||||
const urlParams: any = getState().router.location.params;
|
||||
const deviceId: string = device.features.device_id;
|
||||
const urlParams: RouterLocationState = getState().router.location.state;
|
||||
// let url: string = `/device/${ device.features.device_id }/network/ethereum/address/0`;
|
||||
let url: string = `/device/${ device.features.device_id }`;
|
||||
let instance: ?string;
|
||||
let url: string = `/device/${ deviceId }`;
|
||||
let instance: ?number;
|
||||
// check if device is not TrezorDevice type
|
||||
if (!device.hasOwnProperty('ts')) {
|
||||
// its device from trezor-connect (called in initConnectedDevice triggered by device_connect event)
|
||||
@ -173,15 +252,15 @@ export const onSelectDevice = (device: any): any => {
|
||||
// check if current location is not set to this device
|
||||
//dispatch( push(`/device/${ device.features.device_id }/network/etc/address/0`) );
|
||||
|
||||
if (urlParams.deviceInstance !== instance || urlParams.device !== device.features.device_id) {
|
||||
if (urlParams.deviceInstance !== instance || urlParams.device !== deviceId) {
|
||||
dispatch( push(url) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const switchToFirstAvailableDevice = (): any => {
|
||||
return async (dispatch, getState): Promise<void> => {
|
||||
export const switchToFirstAvailableDevice = (): AsyncAction => {
|
||||
return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||
|
||||
const { devices } = getState().connect;
|
||||
if (devices.length > 0) {
|
||||
@ -208,8 +287,8 @@ export const switchToFirstAvailableDevice = (): any => {
|
||||
}
|
||||
|
||||
|
||||
export const getSelectedDeviceState = (): any => {
|
||||
return async (dispatch, getState): Promise<void> => {
|
||||
export const getSelectedDeviceState = (): AsyncAction => {
|
||||
return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||
const selected = findSelectedDevice(getState().connect);
|
||||
console.warn("init selected", selected)
|
||||
if (selected
|
||||
@ -260,13 +339,13 @@ export const getSelectedDeviceState = (): any => {
|
||||
}
|
||||
}
|
||||
|
||||
export const deviceDisconnect = (device: any): any => {
|
||||
return async (dispatch, getState): Promise<void> => {
|
||||
export const deviceDisconnect = (device: Device): AsyncAction => {
|
||||
return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||
|
||||
const selected = findSelectedDevice(getState().connect);
|
||||
const selected: ?TrezorDevice = findSelectedDevice(getState().connect);
|
||||
|
||||
if (device && device.features) {
|
||||
if (selected && selected.features.device_id === device.features.device_id) {
|
||||
if (selected && selected.features && selected.features.device_id === device.features.device_id) {
|
||||
dispatch( DiscoveryActions.stop(selected) );
|
||||
}
|
||||
|
||||
@ -287,9 +366,11 @@ export const deviceDisconnect = (device: any): any => {
|
||||
}
|
||||
}
|
||||
|
||||
export const coinChanged = (network: ?string): any => {
|
||||
return (dispatch, getState): void => {
|
||||
const selected = findSelectedDevice(getState().connect);
|
||||
export const coinChanged = (network: ?string): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
const selected: ?TrezorDevice = findSelectedDevice(getState().connect);
|
||||
if (!selected) return;
|
||||
|
||||
dispatch( DiscoveryActions.stop(selected) );
|
||||
|
||||
if (network) {
|
||||
@ -298,15 +379,16 @@ export const coinChanged = (network: ?string): any => {
|
||||
}
|
||||
}
|
||||
|
||||
export function reload(): any {
|
||||
return async (dispatch, getState) => {
|
||||
export function reload(): AsyncAction {
|
||||
return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||
}
|
||||
}
|
||||
|
||||
export function acquire(): any {
|
||||
return async (dispatch, getState) => {
|
||||
export function acquire(): AsyncAction {
|
||||
return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||
|
||||
const selected = findSelectedDevice(getState().connect);
|
||||
const selected: ?TrezorDevice = findSelectedDevice(getState().connect);
|
||||
if (!selected) return;
|
||||
|
||||
// const saved = getState().connect.devices.map(d => {
|
||||
// if (d.state) {
|
||||
@ -341,10 +423,11 @@ export function acquire(): any {
|
||||
if (response && response.success) {
|
||||
dispatch({
|
||||
type: DEVICE.ACQUIRED,
|
||||
device: null
|
||||
})
|
||||
} else {
|
||||
// TODO: handle invalid pin?
|
||||
console.log("-errror ack", response)
|
||||
console.log("-error ack", response)
|
||||
|
||||
dispatch({
|
||||
type: NOTIFICATION.ADD,
|
||||
@ -367,35 +450,34 @@ export function acquire(): any {
|
||||
}
|
||||
}
|
||||
|
||||
export const forgetDevice = (device: any) => {
|
||||
return (dispatch: any, getState: any): any => {
|
||||
|
||||
export const forgetDevice = (device: any): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
// find accounts associated with this device
|
||||
const accounts: Array<any> = getState().accounts.find(a => a.deviceState === device.state);
|
||||
// const accounts: Array<any> = getState().accounts.find(a => a.deviceState === device.state);
|
||||
|
||||
|
||||
// find discovery processes associated with this device
|
||||
const discovery: Array<any> = getState().discovery.find(d => d.deviceState === device.state);
|
||||
// const discovery: Array<any> = getState().discovery.find(d => d.deviceState === device.state);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export const gotoDeviceSettings = (device: any) => {
|
||||
return (dispatch: any, getState: any): any => {
|
||||
export const gotoDeviceSettings = (device: any): AsyncAction => {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
dispatch( push(`/device/${ device.features.device_id }/settings`) );
|
||||
}
|
||||
}
|
||||
|
||||
// called from Aside - device menu (forget single instance)
|
||||
export const forget = (device: any) => {
|
||||
export const forget = (device: any): Action => {
|
||||
return {
|
||||
type: CONNECT.FORGET_REQUEST,
|
||||
device
|
||||
};
|
||||
}
|
||||
|
||||
export const duplicateDevice = (device: any) => {
|
||||
return async (dispatch: any, getState: any): Promise<void> => {
|
||||
export const duplicateDevice = (device: any): AsyncAction => {
|
||||
return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||
dispatch({
|
||||
type: CONNECT.TRY_TO_DUPLICATE,
|
||||
device
|
||||
@ -403,17 +485,18 @@ export const duplicateDevice = (device: any) => {
|
||||
}
|
||||
}
|
||||
|
||||
export const onDuplicateDevice = () => {
|
||||
return async (dispatch: any, getState: any): Promise<void> => {
|
||||
const selected = findSelectedDevice(getState().connect);
|
||||
dispatch(onSelectDevice(selected));
|
||||
export const onDuplicateDevice = (): AsyncAction => {
|
||||
return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||
const selected: ?TrezorDevice = findSelectedDevice(getState().connect);
|
||||
if (selected)
|
||||
dispatch(onSelectDevice(selected));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function addAddress(): any {
|
||||
return (dispatch, getState) => {
|
||||
export function addAddress(): AsyncAction {
|
||||
return (dispatch: Dispatch, getState: GetState): void => {
|
||||
const selected = findSelectedDevice(getState().connect);
|
||||
dispatch( DiscoveryActions.start(selected, getState().router.location.params.network, true) ); // TODO: network nicer
|
||||
dispatch( DiscoveryActions.start(selected, getState().router.location.state.network, true) ); // TODO: network nicer
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,28 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
export const ON_RESIZE: string = 'ON_RESIZE';
|
||||
export const TOGGLE_DEVICE_DROPDOWN: string = 'TOGGLE_DEVICE_DROPDOWN';
|
||||
import * as WALLET from './constants/wallet';
|
||||
|
||||
export const onResize = (): any => {
|
||||
return {
|
||||
type: ON_RESIZE
|
||||
}
|
||||
import type { RouterLocationState } from '../flowtype';
|
||||
|
||||
export type WalletAction = {
|
||||
type: typeof WALLET.SET_INITIAL_URL,
|
||||
state?: RouterLocationState,
|
||||
pathname?: string
|
||||
} | {
|
||||
type: typeof WALLET.TOGGLE_DEVICE_DROPDOWN,
|
||||
opened: boolean
|
||||
} | {
|
||||
type: typeof WALLET.ON_BEFORE_UNLOAD
|
||||
}
|
||||
|
||||
export const onBeforeUnload = (): any => {
|
||||
export const onBeforeUnload = (): WalletAction => {
|
||||
return {
|
||||
type: WALLET.ON_BEFORE_UNLOAD
|
||||
}
|
||||
}
|
||||
|
||||
export const toggleDeviceDropdown = (opened: boolean): any => {
|
||||
export const toggleDeviceDropdown = (opened: boolean): WalletAction => {
|
||||
return {
|
||||
type: WALLET.TOGGLE_DEVICE_DROPDOWN,
|
||||
opened
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
import Web3 from 'web3';
|
||||
import Web3, { ContractFactory, Contract } from 'web3';
|
||||
import HDKey from 'hdkey';
|
||||
import EthereumjsUtil from 'ethereumjs-util';
|
||||
import EthereumjsTx from 'ethereumjs-tx';
|
||||
@ -9,48 +9,47 @@ import TrezorConnect from 'trezor-connect';
|
||||
import { strip } from '../utils/ethUtils';
|
||||
import * as ADDRESS from './constants/address';
|
||||
import * as WEB3 from './constants/web3';
|
||||
import { httpRequest } from '../utils/networkUtils';
|
||||
|
||||
type ActionMethod = (dispatch: any, getState: any) => Promise<any>;
|
||||
import type {
|
||||
Dispatch,
|
||||
GetState,
|
||||
Action,
|
||||
AsyncAction,
|
||||
} from '../flowtype';
|
||||
|
||||
type Web3Payload =
|
||||
| {
|
||||
name: string;
|
||||
instance: Web3;
|
||||
chainId: number;
|
||||
erc20abi: any;
|
||||
}
|
||||
| {
|
||||
network: string;
|
||||
blockHash: string;
|
||||
}
|
||||
| {
|
||||
network: string;
|
||||
gasPrice: string;
|
||||
}
|
||||
| {
|
||||
network: string;
|
||||
address: string;
|
||||
balance: string;
|
||||
}
|
||||
| {
|
||||
network: string;
|
||||
address: string;
|
||||
nonce: string;
|
||||
}
|
||||
| {
|
||||
network: string;
|
||||
blockHash: string;
|
||||
import type { Account } from '../reducers/AccountsReducer';
|
||||
|
||||
export type Web3Action = {
|
||||
type: typeof WEB3.READY,
|
||||
} | {
|
||||
type: typeof WEB3.PENDING_TX_RESOLVED
|
||||
} | Web3CreateAction
|
||||
| Web3UpdateBlockAction
|
||||
| Web3UpdateGasPriceAction;
|
||||
|
||||
export type Web3CreateAction = {
|
||||
type: typeof WEB3.CREATE,
|
||||
network: string,
|
||||
web3: any, //(web3instance)
|
||||
erc20: any,
|
||||
chainId: string;
|
||||
};
|
||||
|
||||
type Web3Action = {
|
||||
type: string,
|
||||
payload?: Web3Payload
|
||||
export type Web3UpdateBlockAction = {
|
||||
type: typeof WEB3.BLOCK_UPDATED,
|
||||
network: string,
|
||||
blockHash: any
|
||||
};
|
||||
|
||||
export type Web3UpdateGasPriceAction = {
|
||||
type: typeof WEB3.GAS_PRICE_UPDATED,
|
||||
network: string,
|
||||
gasPrice: any
|
||||
};
|
||||
|
||||
|
||||
export function init(web3: ?Web3, coinIndex: number = 0): ActionMethod {
|
||||
return async (dispatch, getState) => {
|
||||
export function init(web3: ?Web3, coinIndex: number = 0): AsyncAction {
|
||||
return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||
|
||||
const { config, ERC20Abi } = getState().localStorage;
|
||||
|
||||
@ -191,48 +190,48 @@ export function init(web3: ?Web3, coinIndex: number = 0): ActionMethod {
|
||||
}
|
||||
|
||||
|
||||
export function initContracts(): ActionMethod {
|
||||
return async (dispatch, getState) => {
|
||||
const { web3, abi, tokens } = getState().web3;
|
||||
// export function initContracts(): AsyncAction {
|
||||
// return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||
// const { web3, abi, tokens } = getState().web3;
|
||||
|
||||
const contracts = [];
|
||||
for (let token of tokens) {
|
||||
contracts.push({
|
||||
contract: web3.eth.contract(abi).at(token.address),
|
||||
name: token.name,
|
||||
symbol: token.symbol,
|
||||
decimal: token.decimal
|
||||
});
|
||||
// const contracts = [];
|
||||
// for (let token of tokens) {
|
||||
// contracts.push({
|
||||
// contract: web3.eth.contract(abi).at(token.address),
|
||||
// name: token.name,
|
||||
// symbol: token.symbol,
|
||||
// decimal: token.decimal
|
||||
// });
|
||||
|
||||
// web3.eth.contract(abi).at(token.address).balanceOf('0x98ead4bd2fbbb0cf0b49459aa0510ef53faa6cad', (e, r) => {
|
||||
// console.warn('contrR', e, r.toString(10));
|
||||
// });
|
||||
}
|
||||
// // web3.eth.contract(abi).at(token.address).balanceOf('0x98ead4bd2fbbb0cf0b49459aa0510ef53faa6cad', (e, r) => {
|
||||
// // console.warn('contrR', e, r.toString(10));
|
||||
// // });
|
||||
// }
|
||||
|
||||
const contract = web3.eth.contract(abi).at('0x58cda554935e4a1f2acbe15f8757400af275e084');
|
||||
// const contract = web3.eth.contract(abi).at('0x58cda554935e4a1f2acbe15f8757400af275e084');
|
||||
|
||||
contract.name.call((error, name) => {
|
||||
if (error) {
|
||||
// TODO: skip
|
||||
}
|
||||
contract.symbol.call((error, symbol) => {
|
||||
if (error) {
|
||||
// TODO: skip
|
||||
}
|
||||
// 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("nameeeee", name, symbol, decimals)
|
||||
})
|
||||
});
|
||||
// contract.decimals.call((error, decimals) => {
|
||||
// console.log("nameeeee", name, symbol, decimals)
|
||||
// })
|
||||
// });
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
export function getGasPrice(network: string): ActionMethod {
|
||||
return async (dispatch, getState) => {
|
||||
export function getGasPrice(network: string): AsyncAction {
|
||||
return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||
|
||||
const index: number = getState().web3.findIndex(w3 => w3.network === network);
|
||||
|
||||
@ -252,20 +251,20 @@ export function getGasPrice(network: string): ActionMethod {
|
||||
}
|
||||
}
|
||||
|
||||
export function getBalance(addr: Address): ActionMethod {
|
||||
return async (dispatch, getState) => {
|
||||
export function getBalance(account: Account): AsyncAction {
|
||||
return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||
|
||||
const web3instance = getState().web3.filter(w3 => w3.network === addr.network)[0];
|
||||
const web3 = web3instance.web3;
|
||||
const web3instance = getState().web3.filter(w3 => w3.network === account.network)[0];
|
||||
const web3: Web3 = web3instance.web3;
|
||||
|
||||
web3.eth.getBalance(addr.address, (error, balance) => {
|
||||
web3.eth.getBalance(account.address, (error, balance) => {
|
||||
if (!error) {
|
||||
const newBalance: string = web3.fromWei(balance.toString(), 'ether');
|
||||
if (addr.balance !== newBalance) {
|
||||
if (account.balance !== newBalance) {
|
||||
dispatch({
|
||||
type: ADDRESS.SET_BALANCE,
|
||||
address: addr.address,
|
||||
network: addr.network,
|
||||
address: account.address,
|
||||
network: account.network,
|
||||
balance: newBalance
|
||||
});
|
||||
|
||||
@ -276,20 +275,20 @@ export function getBalance(addr: Address): ActionMethod {
|
||||
}
|
||||
}
|
||||
|
||||
export function getNonce(addr: Address) {
|
||||
export function getNonce(account: Account): AsyncAction {
|
||||
|
||||
return async (dispatch, getState) => {
|
||||
return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||
|
||||
const web3instance = getState().web3.filter(w3 => w3.network === addr.network)[0];
|
||||
const web3instance = getState().web3.filter(w3 => w3.network === account.network)[0];
|
||||
const web3 = web3instance.web3;
|
||||
|
||||
web3.eth.getTransactionCount(addr.address, (error, result) => {
|
||||
web3.eth.getTransactionCount(account.address, (error, result) => {
|
||||
if (!error) {
|
||||
if (addr.nonce !== result) {
|
||||
if (account.nonce !== result) {
|
||||
dispatch({
|
||||
type: ADDRESS.SET_NONCE,
|
||||
address: addr.address,
|
||||
network: addr.network,
|
||||
address: account.address,
|
||||
network: account.network,
|
||||
nonce: result
|
||||
});
|
||||
}
|
||||
@ -298,8 +297,8 @@ export function getNonce(addr: Address) {
|
||||
}
|
||||
}
|
||||
|
||||
export function getTransactionReceipt(tx: any): any {
|
||||
return async (dispatch, getState) => {
|
||||
export function getTransactionReceipt(tx: any): AsyncAction {
|
||||
return async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||
|
||||
const web3instance = getState().web3.filter(w3 => w3.network === tx.network)[0];
|
||||
const web3 = web3instance.web3;
|
||||
@ -323,14 +322,14 @@ export function getTransactionReceipt(tx: any): any {
|
||||
}
|
||||
|
||||
|
||||
export function updateLastBlock(hash: string) {
|
||||
return {
|
||||
type: 'web3__update_last_block',
|
||||
hash
|
||||
}
|
||||
}
|
||||
// export function updateLastBlock(hash: string): Action {
|
||||
// return {
|
||||
// type: 'web3__update_last_block',
|
||||
// hash
|
||||
// }
|
||||
// }
|
||||
|
||||
export function getTransaction(web3, txid) {
|
||||
export const getTransaction = (web3: Web3, txid: string): Promise<any> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
web3.eth.getTransaction(txid, (error, result) => {
|
||||
if (error) {
|
||||
@ -344,7 +343,7 @@ export function getTransaction(web3, txid) {
|
||||
|
||||
|
||||
|
||||
export function getBalanceAsync(web3, address) {
|
||||
export const getBalanceAsync = (web3: Web3, address: string): Promise<any> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
web3.eth.getBalance(address, (error, result) => {
|
||||
if (error) {
|
||||
@ -356,7 +355,7 @@ export function getBalanceAsync(web3, address) {
|
||||
});
|
||||
}
|
||||
|
||||
export const getTokenBalanceAsync = (erc20: any, token: any, address: any): Promise<any> => {
|
||||
export const getTokenBalanceAsync = (erc20: any, token: string, address: string): Promise<any> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
const contr = erc20.at(token);
|
||||
@ -370,7 +369,7 @@ export const getTokenBalanceAsync = (erc20: any, token: any, address: any): Prom
|
||||
});
|
||||
}
|
||||
|
||||
export function getNonceAsync(web3, address) {
|
||||
export const getNonceAsync = (web3: Web3, address: string): Promise<any> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
web3.eth.getTransactionCount(address, (error, result) => {
|
||||
if (error) {
|
||||
@ -383,7 +382,7 @@ export function getNonceAsync(web3, address) {
|
||||
}
|
||||
|
||||
|
||||
export function getTokenInfoAsync(erc20: any, address: string): Promise<any> {
|
||||
export const getTokenInfoAsync = (erc20: any, address: string): Promise<any> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
const contract = erc20.at(address);
|
||||
@ -417,7 +416,7 @@ export function getTokenInfoAsync(erc20: any, address: string): Promise<any> {
|
||||
});
|
||||
}
|
||||
|
||||
export function estimateGas(web3, gasOptions) {
|
||||
export const estimateGas = (web3: Web3, gasOptions: any): Promise<any> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
web3.eth.estimateGas(gasOptions, (error, result) => {
|
||||
if (error) {
|
||||
@ -429,7 +428,7 @@ export function estimateGas(web3, gasOptions) {
|
||||
})
|
||||
}
|
||||
|
||||
export function getGasPrice2(web3) {
|
||||
export const getGasPrice2 = (web3: Web3): Promise<any> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
web3.eth.getGasPrice((error, result) => {
|
||||
if (error) {
|
||||
@ -441,7 +440,7 @@ export function getGasPrice2(web3) {
|
||||
})
|
||||
}
|
||||
|
||||
export function pushTx(web3, tx) {
|
||||
export const pushTx = (web3: Web3, tx: any): Promise<any> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
web3.eth.sendRawTransaction(tx, (error, result) => {
|
||||
if (error) {
|
||||
@ -452,7 +451,3 @@ export function pushTx(web3, tx) {
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,26 +1,29 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
export const READY: string = 'trezorconnect__ready';
|
||||
export const INITIALIZATION_ERROR: string = 'trezorconnect__init_error';
|
||||
export const SELECT_DEVICE: string = 'trezorconnect__select_device';
|
||||
//regExp1 : string = '(.*)'
|
||||
//regExp2 : '$1' = '$1'
|
||||
|
||||
export const READY: 'trezorconnect__ready' = 'trezorconnect__ready';
|
||||
export const INITIALIZATION_ERROR: 'trezorconnect__init_error' = 'trezorconnect__init_error';
|
||||
export const SELECT_DEVICE: 'trezorconnect__select_device' = 'trezorconnect__select_device';
|
||||
|
||||
|
||||
export const DEVICE_FROM_STORAGE: string = 'trezorconnect__device_from_storage';
|
||||
export const AUTH_DEVICE: string = 'trezorconnect__auth_device';
|
||||
export const COIN_CHANGED: string = 'trezorconnect__coin_changed';
|
||||
export const DEVICE_FROM_STORAGE: 'trezorconnect__device_from_storage' = 'trezorconnect__device_from_storage';
|
||||
export const AUTH_DEVICE: 'trezorconnect__auth_device' = 'trezorconnect__auth_device';
|
||||
export const COIN_CHANGED: 'trezorconnect__coin_changed' = 'trezorconnect__coin_changed';
|
||||
|
||||
export const REMEMBER_REQUEST: string = 'trezorconnect__remember_request';
|
||||
export const FORGET_REQUEST: string = 'trezorconnect__forget_request';
|
||||
export const FORGET: string = 'trezorconnect__forget';
|
||||
export const FORGET_SINGLE: string = 'trezorconnect__forget_single';
|
||||
export const DISCONNECT_REQUEST: string = 'trezorconnect__disconnect_request';
|
||||
export const REMEMBER: string = 'trezorconnect__remember';
|
||||
export const REMEMBER_REQUEST: 'trezorconnect__remember_request' = 'trezorconnect__remember_request';
|
||||
export const FORGET_REQUEST: 'trezorconnect__forget_request' = 'trezorconnect__forget_request';
|
||||
export const FORGET: 'trezorconnect__forget' = 'trezorconnect__forget';
|
||||
export const FORGET_SINGLE: 'trezorconnect__forget_single' = 'trezorconnect__forget_single';
|
||||
export const DISCONNECT_REQUEST: 'trezorconnect__disconnect_request' = 'trezorconnect__disconnect_request';
|
||||
export const REMEMBER: 'trezorconnect__remember' = 'trezorconnect__remember';
|
||||
|
||||
export const START_ACQUIRING: string = 'trezorconnect__start_acquiring';
|
||||
export const STOP_ACQUIRING: string = 'trezorconnect__stop_acquiring';
|
||||
export const START_ACQUIRING: 'trezorconnect__start_acquiring' = 'trezorconnect__start_acquiring';
|
||||
export const STOP_ACQUIRING: 'trezorconnect__stop_acquiring' = 'trezorconnect__stop_acquiring';
|
||||
|
||||
export const TRY_TO_DUPLICATE: string = 'trezorconnect__try_to_duplicate';
|
||||
export const DUPLICATE: string = 'trezorconnect__duplicate';
|
||||
export const TRY_TO_DUPLICATE: 'trezorconnect__try_to_duplicate' = 'trezorconnect__try_to_duplicate';
|
||||
export const DUPLICATE: 'trezorconnect__duplicate' = 'trezorconnect__duplicate';
|
||||
|
||||
export const DEVICE_STATE_EXCEPTION: string = 'trezorconnect__device_state_exception';
|
||||
export const DEVICE_STATE_EXCEPTION: 'trezorconnect__device_state_exception' = 'trezorconnect__device_state_exception';
|
@ -1,11 +1,11 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
export const INIT: string = 'account__init';
|
||||
export const DISPOSE: string = 'account__dispose';
|
||||
export const INIT: 'account__init' = 'account__init';
|
||||
export const DISPOSE: 'account__dispose' = 'account__dispose';
|
||||
|
||||
export const CREATE: string = 'address__create';
|
||||
export const REMOVE: string = 'address__remove';
|
||||
export const SET_BALANCE: string = 'address__set_balance';
|
||||
export const SET_NONCE: string = 'address__set_nonce';
|
||||
export const FROM_STORAGE: string = 'address__from_storage';
|
||||
// export const CREATE: 'address__create' = 'address__create';
|
||||
// export const REMOVE: 'address__remove' = 'address__remove';
|
||||
// export const SET_BALANCE: 'address__set_balance' = 'address__set_balance';
|
||||
// export const SET_NONCE: 'address__set_nonce' = 'address__set_nonce';
|
||||
// export const FROM_STORAGE: 'address__from_storage' = 'address__from_storage';
|
@ -1,9 +1,9 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
export const CREATE: string = 'address__create';
|
||||
export const REMOVE: string = 'address__remove';
|
||||
export const SET_BALANCE: string = 'address__set_balance';
|
||||
export const SET_NONCE: string = 'address__set_nonce';
|
||||
export const FROM_STORAGE: string = 'address__from_storage';
|
||||
export const CREATE: 'address__create' = 'address__create';
|
||||
export const REMOVE: 'address__remove' = 'address__remove';
|
||||
export const SET_BALANCE: 'address__set_balance' = 'address__set_balance';
|
||||
export const SET_NONCE: 'address__set_nonce' = 'address__set_nonce';
|
||||
export const FROM_STORAGE: 'address__from_storage' = 'address__from_storage';
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
export const START: string = 'discovery__start';
|
||||
export const STOP: string = 'discovery__stop';
|
||||
export const COMPLETE: string = 'discovery__complete';
|
||||
export const WAITING: string = 'discovery__waiting';
|
||||
export const FROM_STORAGE: string = 'discovery__from_storage';
|
||||
export const START: 'discovery__start' = 'discovery__start';
|
||||
export const STOP: 'discovery__stop' = 'discovery__stop';
|
||||
export const COMPLETE: 'discovery__complete' = 'discovery__complete';
|
||||
export const WAITING: 'discovery__waiting' = 'discovery__waiting';
|
||||
export const FROM_STORAGE: 'discovery__from_storage' = 'discovery__from_storage';
|
@ -1,6 +1,6 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
export const SAVE: string = 'storage__save';
|
||||
export const READY: string = 'storage__ready';
|
||||
export const ERROR: string = 'storage__error';
|
||||
export const SAVE: 'storage__save' = 'storage__save';
|
||||
export const READY: 'storage__ready' = 'storage__ready';
|
||||
export const ERROR: 'storage__error' = 'storage__error';
|
5
src/js/actions/constants/log.js
Normal file
5
src/js/actions/constants/log.js
Normal file
@ -0,0 +1,5 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
export const OPEN: 'log__open' = 'log__open';
|
||||
export const CLOSE: 'log__close' = 'log__close';
|
@ -1,14 +1,17 @@
|
||||
export const ON_PASSPHRASE_CHANGE: string = 'action__on_passphrase_change';
|
||||
export const ON_PASSPHRASE_SHOW: string = 'action__on_passphrase_show';
|
||||
export const ON_PASSPHRASE_HIDE: string = 'action__on_passphrase_hide';
|
||||
export const ON_PASSPHRASE_SAVE: string = 'action__on_passphrase_save';
|
||||
export const ON_PASSPHRASE_FORGET: string = 'action__on_passphrase_forget';
|
||||
export const ON_PASSPHRASE_FOCUS: string = 'action__on_passphrase_focus';
|
||||
export const ON_PASSPHRASE_BLUR: string = 'action__on_passphrase_blur';
|
||||
export const ON_PASSPHRASE_SUBMIT: string = 'action__on_passphrase_submit';
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
export const FORGET: string = 'modal__forget';
|
||||
export const REMEMBER: string = 'modal__remember';
|
||||
export const ON_FORGET: string = 'modal__on_forget';
|
||||
export const ON_REMEMBER: string = 'modal__on_remember';
|
||||
export const CLOSE: string = 'modal__close';
|
||||
export const ON_PASSPHRASE_CHANGE: 'action__on_passphrase_change' = 'action__on_passphrase_change';
|
||||
export const ON_PASSPHRASE_SHOW: 'action__on_passphrase_show' = 'action__on_passphrase_show';
|
||||
export const ON_PASSPHRASE_HIDE: 'action__on_passphrase_hide' = 'action__on_passphrase_hide';
|
||||
export const ON_PASSPHRASE_SAVE: 'action__on_passphrase_save' = 'action__on_passphrase_save';
|
||||
export const ON_PASSPHRASE_FORGET: 'action__on_passphrase_forget' = 'action__on_passphrase_forget';
|
||||
export const ON_PASSPHRASE_FOCUS: 'action__on_passphrase_focus' = 'action__on_passphrase_focus';
|
||||
export const ON_PASSPHRASE_BLUR: 'action__on_passphrase_blur' = 'action__on_passphrase_blur';
|
||||
export const ON_PASSPHRASE_SUBMIT: 'action__on_passphrase_submit' = 'action__on_passphrase_submit';
|
||||
|
||||
export const FORGET: 'modal__forget' = 'modal__forget';
|
||||
export const REMEMBER: 'modal__remember' = 'modal__remember';
|
||||
export const ON_FORGET: 'modal__on_forget' = 'modal__on_forget';
|
||||
export const ON_REMEMBER: 'modal__on_remember' = 'modal__on_remember';
|
||||
export const CLOSE: 'modal__close' = 'modal__close';
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
export const ADD: string = 'notification__add';
|
||||
export const CLOSE: string = 'notification__close';
|
||||
export const REMOVE: string = 'account__remove';
|
||||
export const ADD: 'notification__add' = 'notification__add';
|
||||
export const CLOSE: 'notification__close' = 'notification__close';
|
||||
export const REMOVE: 'account__remove' = 'account__remove';
|
@ -1,8 +1,8 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
export const INIT: string = 'receive__init';
|
||||
export const DISPOSE: string = 'receive__dispose';
|
||||
export const REQUEST_UNVERIFIED: string = 'receive__request_unverified';
|
||||
export const SHOW_ADDRESS: string = 'receive__show_address';
|
||||
export const SHOW_UNVERIFIED_ADDRESS: string = 'receive__show_unverified';
|
||||
export const INIT: 'receive__init' = 'receive__init';
|
||||
export const DISPOSE: 'receive__dispose' = 'receive__dispose';
|
||||
export const REQUEST_UNVERIFIED: 'receive__request_unverified' = 'receive__request_unverified';
|
||||
export const SHOW_ADDRESS: 'receive__show_address' = 'receive__show_address';
|
||||
export const SHOW_UNVERIFIED_ADDRESS: 'receive__show_unverified' = 'receive__show_unverified';
|
||||
|
@ -1,19 +1,19 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
export const INIT: string = 'send__init';
|
||||
export const DISPOSE: string = 'send__dispose';
|
||||
export const VALIDATION: string = 'send__validation';
|
||||
export const ADDRESS_CHANGE: string = 'send__address_change';
|
||||
export const AMOUNT_CHANGE: string = 'send__amount_change';
|
||||
export const SET_MAX: string = 'send__set_max';
|
||||
export const CURRENCY_CHANGE: string = 'send__currency_change';
|
||||
export const FEE_LEVEL_CHANGE: string = 'send__fee_level_change';
|
||||
export const GAS_PRICE_CHANGE: string = 'send__gas_price_change';
|
||||
export const GAS_LIMIT_CHANGE: string = 'send__gas_limit_change';
|
||||
export const UPDATE_FEE_LEVELS: string = 'send__update_fee_levels';
|
||||
export const DATA_CHANGE: string = 'send__data_change';
|
||||
export const SEND: string = 'send__submit';
|
||||
export const TX_COMPLETE: string = 'send__tx_complete';
|
||||
export const TX_ERROR: string = 'send__tx_error';
|
||||
export const TOGGLE_ADVANCED: string = 'send__toggle_advanced';
|
||||
export const INIT: 'send__init' = 'send__init';
|
||||
export const DISPOSE: 'send__dispose' = 'send__dispose';
|
||||
export const VALIDATION: 'send__validation' = 'send__validation';
|
||||
export const ADDRESS_CHANGE: 'send__address_change' = 'send__address_change';
|
||||
export const AMOUNT_CHANGE: 'send__amount_change' = 'send__amount_change';
|
||||
export const SET_MAX: 'send__set_max' = 'send__set_max';
|
||||
export const CURRENCY_CHANGE: 'send__currency_change' = 'send__currency_change';
|
||||
export const FEE_LEVEL_CHANGE: 'send__fee_level_change' = 'send__fee_level_change';
|
||||
export const GAS_PRICE_CHANGE: 'send__gas_price_change' = 'send__gas_price_change';
|
||||
export const GAS_LIMIT_CHANGE: 'send__gas_limit_change' = 'send__gas_limit_change';
|
||||
export const UPDATE_FEE_LEVELS: 'send__update_fee_levels' = 'send__update_fee_levels';
|
||||
export const DATA_CHANGE: 'send__data_change' = 'send__data_change';
|
||||
export const SEND: 'send__submit' = 'send__submit';
|
||||
export const TX_COMPLETE: 'send__tx_complete' = 'send__tx_complete';
|
||||
export const TX_ERROR: 'send__tx_error' = 'send__tx_error';
|
||||
export const TOGGLE_ADVANCED: 'send__toggle_advanced' = 'send__toggle_advanced';
|
@ -1,7 +1,7 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
export const INIT: string = 'summary__init';
|
||||
export const DISPOSE: string = 'summary__dispose';
|
||||
export const ADD_TOKEN: string = 'summary__add_token';
|
||||
export const DETAILS_TOGGLE: string = 'summary__details_toggle';
|
||||
export const INIT: 'summary__init' = 'summary__init';
|
||||
export const DISPOSE: 'summary__dispose' = 'summary__dispose';
|
||||
export const ADD_TOKEN: 'summary__add_token' = 'summary__add_token';
|
||||
export const DETAILS_TOGGLE: 'summary__details_toggle' = 'summary__details_toggle';
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
export const ADD: string = 'token__add';
|
||||
export const REMOVE: string = 'token__remove';
|
||||
export const SET_BALANCE: string = 'token__set_balance';
|
||||
export const FROM_STORAGE: string = 'token__from_storage';
|
||||
export const ADD: 'token__add' = 'token__add';
|
||||
export const REMOVE: 'token__remove' = 'token__remove';
|
||||
export const SET_BALANCE: 'token__set_balance' = 'token__set_balance';
|
||||
export const FROM_STORAGE: 'token__from_storage' = 'token__from_storage';
|
@ -1,6 +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';
|
||||
export const ON_BEFORE_UNLOAD: 'wallet__on_before_unload' = 'wallet__on_before_unload';
|
||||
export const TOGGLE_DEVICE_DROPDOWN: 'wallet_toggle_dropdown' = 'wallet_toggle_dropdown';
|
||||
export const SET_INITIAL_URL: 'wallet_set_initial_url' = 'wallet_set_initial_url';
|
@ -1,10 +1,10 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
export const START: string = 'web3__start';
|
||||
export const STOP: string = 'web3__stop';
|
||||
export const CREATE: string = 'web3__create';
|
||||
export const READY: string = 'web3__ready';
|
||||
export const BLOCK_UPDATED: string = 'web3__block_updated';
|
||||
export const GAS_PRICE_UPDATED: string = 'web3__gas_price_updated';
|
||||
export const PENDING_TX_RESOLVED: string = 'web3__pending_tx_resolved';
|
||||
export const START: 'web3__start' = 'web3__start';
|
||||
export const STOP: 'web3__stop' = 'web3__stop';
|
||||
export const CREATE: 'web3__create' = 'web3__create';
|
||||
export const READY: 'web3__ready' = 'web3__ready';
|
||||
export const BLOCK_UPDATED: 'web3__block_updated' = 'web3__block_updated';
|
||||
export const GAS_PRICE_UPDATED: 'web3__gas_price_updated' = 'web3__gas_price_updated';
|
||||
export const PENDING_TX_RESOLVED: 'web3__pending_tx_resolved' = 'web3__pending_tx_resolved';
|
@ -6,8 +6,13 @@ import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import * as LogActions from '../../actions/LogActions';
|
||||
import type { State, Dispatch } from '../../flowtype';
|
||||
|
||||
const Footer = (props: any): any => {
|
||||
type Props = {
|
||||
toggle: typeof LogActions.toggle
|
||||
}
|
||||
|
||||
const Footer = (props: Props): React$Element<string> => {
|
||||
return (
|
||||
<footer>
|
||||
<span>© 2018</span>
|
||||
@ -19,12 +24,12 @@ const Footer = (props: any): any => {
|
||||
}
|
||||
|
||||
export default connect(
|
||||
(state) => {
|
||||
(state: State) => {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
(dispatch) => {
|
||||
(dispatch: Dispatch) => {
|
||||
return {
|
||||
toggle: bindActionCreators(LogActions.toggle, dispatch),
|
||||
};
|
||||
|
@ -1,33 +1,30 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import React from 'react';
|
||||
|
||||
export default class Header extends Component {
|
||||
render() {
|
||||
return (
|
||||
<header>
|
||||
<div className="layout-wrapper">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 163.7 41.9" width="100%" height="100%" preserveAspectRatio="xMinYMin meet">
|
||||
<polygon points="101.1,12.8 118.2,12.8 118.2,17.3 108.9,29.9 118.2,29.9 118.2,35.2 101.1,35.2 101.1,30.7 110.4,18.1 101.1,18.1"/>
|
||||
<path d="M158.8,26.9c2.1-0.8,4.3-2.9,4.3-6.6c0-4.5-3.1-7.4-7.7-7.4h-10.5v22.3h5.8v-7.5h2.2l4.1,7.5h6.7L158.8,26.9z M154.7,22.5 h-4V18h4c1.5,0,2.5,0.9,2.5,2.2C157.2,21.6,156.2,22.5,154.7,22.5z"/>
|
||||
<path d="M130.8,12.5c-6.8,0-11.6,4.9-11.6,11.5s4.9,11.5,11.6,11.5s11.7-4.9,11.7-11.5S137.6,12.5,130.8,12.5z M130.8,30.3 c-3.4,0-5.7-2.6-5.7-6.3c0-3.8,2.3-6.3,5.7-6.3c3.4,0,5.8,2.6,5.8,6.3C136.6,27.7,134.2,30.3,130.8,30.3z"/>
|
||||
<polygon points="82.1,12.8 98.3,12.8 98.3,18 87.9,18 87.9,21.3 98,21.3 98,26.4 87.9,26.4 87.9,30 98.3,30 98.3,35.2 82.1,35.2 "/>
|
||||
<path d="M24.6,9.7C24.6,4.4,20,0,14.4,0S4.2,4.4,4.2,9.7v3.1H0v22.3h0l14.4,6.7l14.4-6.7h0V12.9h-4.2V9.7z M9.4,9.7 c0-2.5,2.2-4.5,5-4.5s5,2,5,4.5v3.1H9.4V9.7z M23,31.5l-8.6,4l-8.6-4V18.1H23V31.5z"/>
|
||||
<path d="M79.4,20.3c0-4.5-3.1-7.4-7.7-7.4H61.2v22.3H67v-7.5h2.2l4.1,7.5H80l-4.9-8.3C77.2,26.1,79.4,24,79.4,20.3z M71,22.5h-4V18 h4c1.5,0,2.5,0.9,2.5,2.2C73.5,21.6,72.5,22.5,71,22.5z"/>
|
||||
<polygon points="40.5,12.8 58.6,12.8 58.6,18.1 52.4,18.1 52.4,35.2 46.6,35.2 46.6,18.1 40.5,18.1 "/>
|
||||
</svg>
|
||||
<div>
|
||||
<a href="https://trezor.io/" target="_blank" rel="noreferrer noopener">TREZOR</a>
|
||||
<a href="https://doc.satoshilabs.com/trezor-user/" target="_blank" rel="noreferrer noopener">Docs</a>
|
||||
<a href="https://blog.trezor.io/" target="_blank" rel="noreferrer noopener">Blog</a>
|
||||
<a href="https://trezor.io/support/" target="_blank" rel="noreferrer noopener">Support</a>
|
||||
</div>
|
||||
const Header = (): React$Element<string> => {
|
||||
return (
|
||||
<header>
|
||||
<div className="layout-wrapper">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 163.7 41.9" width="100%" height="100%" preserveAspectRatio="xMinYMin meet">
|
||||
<polygon points="101.1,12.8 118.2,12.8 118.2,17.3 108.9,29.9 118.2,29.9 118.2,35.2 101.1,35.2 101.1,30.7 110.4,18.1 101.1,18.1"/>
|
||||
<path d="M158.8,26.9c2.1-0.8,4.3-2.9,4.3-6.6c0-4.5-3.1-7.4-7.7-7.4h-10.5v22.3h5.8v-7.5h2.2l4.1,7.5h6.7L158.8,26.9z M154.7,22.5 h-4V18h4c1.5,0,2.5,0.9,2.5,2.2C157.2,21.6,156.2,22.5,154.7,22.5z"/>
|
||||
<path d="M130.8,12.5c-6.8,0-11.6,4.9-11.6,11.5s4.9,11.5,11.6,11.5s11.7-4.9,11.7-11.5S137.6,12.5,130.8,12.5z M130.8,30.3 c-3.4,0-5.7-2.6-5.7-6.3c0-3.8,2.3-6.3,5.7-6.3c3.4,0,5.8,2.6,5.8,6.3C136.6,27.7,134.2,30.3,130.8,30.3z"/>
|
||||
<polygon points="82.1,12.8 98.3,12.8 98.3,18 87.9,18 87.9,21.3 98,21.3 98,26.4 87.9,26.4 87.9,30 98.3,30 98.3,35.2 82.1,35.2 "/>
|
||||
<path d="M24.6,9.7C24.6,4.4,20,0,14.4,0S4.2,4.4,4.2,9.7v3.1H0v22.3h0l14.4,6.7l14.4-6.7h0V12.9h-4.2V9.7z M9.4,9.7 c0-2.5,2.2-4.5,5-4.5s5,2,5,4.5v3.1H9.4V9.7z M23,31.5l-8.6,4l-8.6-4V18.1H23V31.5z"/>
|
||||
<path d="M79.4,20.3c0-4.5-3.1-7.4-7.7-7.4H61.2v22.3H67v-7.5h2.2l4.1,7.5H80l-4.9-8.3C77.2,26.1,79.4,24,79.4,20.3z M71,22.5h-4V18 h4c1.5,0,2.5,0.9,2.5,2.2C73.5,21.6,72.5,22.5,71,22.5z"/>
|
||||
<polygon points="40.5,12.8 58.6,12.8 58.6,18.1 52.4,18.1 52.4,35.2 46.6,35.2 46.6,18.1 40.5,18.1 "/>
|
||||
</svg>
|
||||
<div>
|
||||
<a href="https://trezor.io/" target="_blank" rel="noreferrer noopener">TREZOR</a>
|
||||
<a href="https://doc.satoshilabs.com/trezor-user/" target="_blank" rel="noreferrer noopener">Docs</a>
|
||||
<a href="https://blog.trezor.io/" target="_blank" rel="noreferrer noopener">Blog</a>
|
||||
<a href="https://trezor.io/support/" target="_blank" rel="noreferrer noopener">Support</a>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
export default Header;
|
@ -3,7 +3,7 @@
|
||||
|
||||
import React from 'react';
|
||||
|
||||
export default (props: any): any => {
|
||||
export default (props: { size: string, label?: string }): React$Element<string> => {
|
||||
|
||||
const style = {
|
||||
width: `${props.size}px`,
|
||||
|
@ -6,9 +6,14 @@ import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import * as LogActions from '../../actions/LogActions';
|
||||
import type { State, Dispatch } from '../../flowtype';
|
||||
|
||||
const Log = (props: any) => {
|
||||
type Props = {
|
||||
log: $ElementType<State, 'log'>,
|
||||
toggle: typeof LogActions.toggle
|
||||
}
|
||||
|
||||
const Log = (props: Props): ?React$Element<string> => {
|
||||
if (!props.log.opened)
|
||||
return null;
|
||||
|
||||
@ -23,12 +28,12 @@ const Log = (props: any) => {
|
||||
}
|
||||
|
||||
export default connect(
|
||||
(state) => {
|
||||
(state: State) => {
|
||||
return {
|
||||
log: state.log
|
||||
};
|
||||
},
|
||||
(dispatch) => {
|
||||
(dispatch: Dispatch) => {
|
||||
return {
|
||||
toggle: bindActionCreators(LogActions.toggle, dispatch),
|
||||
};
|
||||
|
@ -6,23 +6,37 @@ import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import * as NOTIFICATION from '../../actions/constants/notification';
|
||||
import type { Action, State, Dispatch } from '../../flowtype';
|
||||
|
||||
type Props = {
|
||||
notifications: $ElementType<State, 'notifications'>,
|
||||
close: (notif?: any) => Action
|
||||
}
|
||||
|
||||
export const Notification = (props: any) => {
|
||||
type NProps = {
|
||||
key?: number;
|
||||
className: string;
|
||||
cancelable?: boolean;
|
||||
title: string;
|
||||
message?: string;
|
||||
actions?: Array<any>;
|
||||
close?: (notif?: any) => Action
|
||||
}
|
||||
|
||||
export const Notification = (props: NProps): React$Element<string> => {
|
||||
const className = `notification ${ props.className }`;
|
||||
|
||||
|
||||
const actionButtons = !props.actions ? null : props.actions.map((a, i) => {
|
||||
const close: Function = typeof props.close === 'function' ? props.close : () => {}; // TODO: add default close action
|
||||
const actionButtons = props.actions ? props.actions.map((a, i) => {
|
||||
return (
|
||||
<button key={ i } onClick={ event => { props.close(); a.callback(); } } className="transparent">{ a.label }</button>
|
||||
<button key={ i } onClick={ event => { close(); a.callback(); } } className="transparent">{ a.label }</button>
|
||||
)
|
||||
});
|
||||
}) : null;
|
||||
|
||||
return (
|
||||
<div className={ className }>
|
||||
{ props.cancelable ? (
|
||||
<button className="notification-close transparent"
|
||||
onClick={ event => props.close() }></button>
|
||||
onClick={ event => close() }></button>
|
||||
) : null }
|
||||
<div className="notification-body">
|
||||
<h2>{ props.title }</h2>
|
||||
@ -38,7 +52,7 @@ export const Notification = (props: any) => {
|
||||
)
|
||||
}
|
||||
|
||||
export const NotificationGroup = (props: any) => {
|
||||
export const NotificationGroup = (props: Props) => {
|
||||
const { notifications, close } = props;
|
||||
return notifications.map((n, i) => {
|
||||
return (
|
||||
@ -56,14 +70,14 @@ export const NotificationGroup = (props: any) => {
|
||||
}
|
||||
|
||||
export default connect(
|
||||
(state) => {
|
||||
(state: State) => {
|
||||
return {
|
||||
notifications: state.notifications
|
||||
};
|
||||
},
|
||||
(dispatch) => {
|
||||
(dispatch: Dispatch) => {
|
||||
return {
|
||||
close: bindActionCreators((notif) => {
|
||||
close: bindActionCreators((notif?: any): Action => {
|
||||
return {
|
||||
type: NOTIFICATION.CLOSE,
|
||||
payload: notif
|
||||
|
@ -4,8 +4,11 @@
|
||||
import React, { Component } from 'react';
|
||||
import TrezorConnect from 'trezor-connect';
|
||||
|
||||
export default class InstallBridge extends Component {
|
||||
type Props = {
|
||||
transport: any;
|
||||
}
|
||||
|
||||
export default class InstallBridge extends Component<Props> {
|
||||
|
||||
componentDidMount(): void {
|
||||
const transport: any = this.props.transport;
|
||||
|
@ -7,27 +7,39 @@ import Select from 'react-select';
|
||||
|
||||
type State = {
|
||||
version: string;
|
||||
target: string;
|
||||
target: ?InstallTarget;
|
||||
url: string;
|
||||
}
|
||||
|
||||
const installers = [
|
||||
type InstallTarget = {
|
||||
id: string;
|
||||
value: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
const installers: Array<InstallTarget> = [
|
||||
{ id: 'Windows', value: 'trezor-bridge-2.0.11-win32-install.exe', label: 'Windows' },
|
||||
{ id: 'macOS', value: 'trezor-bridge-2.0.11.pkg', label: 'Mac OS X' },
|
||||
{ id: 'Linux', value: 'trezor-bridge_2.0.11_amd64.deb', label: 'Linux 64-bit (deb)' },
|
||||
{ id: 'Linux-rpm', value: 'trezor-bridge_2.0.11_amd64.rpm', label: 'Linux 64-bit (rpm)' },
|
||||
{ value: 'trezor-bridge_2.0.11_amd32.deb', label: 'Linux 32-bit (deb)' },
|
||||
{ value: 'trezor-bridge_2.0.11_amd32.rpm', label: 'Linux 32-bit (rpm)' },
|
||||
{ id: '01', value: 'trezor-bridge_2.0.11_amd32.deb', label: 'Linux 32-bit (deb)' },
|
||||
{ id: '02', value: 'trezor-bridge_2.0.11_amd32.rpm', label: 'Linux 32-bit (rpm)' },
|
||||
];
|
||||
|
||||
export default class InstallBridge extends Component {
|
||||
// import type { Props } from './index';
|
||||
|
||||
state: State;
|
||||
type Props = {
|
||||
browserState: {
|
||||
osname: string,
|
||||
};
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
export default class InstallBridge extends Component<Props, State> {
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
const currentTarget = installers.find(i => i.id === props.browserState.osname);
|
||||
const currentTarget: ?InstallTarget = installers.find(i => i.id === props.browserState.osname);
|
||||
this.state = {
|
||||
version: '2.0.12',
|
||||
url: 'https://wallet.trezor.io/data/bridge/2.0.12/',
|
||||
@ -35,7 +47,7 @@ export default class InstallBridge extends Component {
|
||||
};
|
||||
}
|
||||
|
||||
onChange(value) {
|
||||
onChange(value: InstallTarget) {
|
||||
this.setState({
|
||||
target: value
|
||||
});
|
||||
@ -44,7 +56,7 @@ 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);
|
||||
const currentTarget: ?InstallTarget = installers.find(i => i.id === this.props.browserState.osname);
|
||||
this.setState({
|
||||
target: currentTarget
|
||||
})
|
||||
@ -55,8 +67,9 @@ export default class InstallBridge extends Component {
|
||||
if (!this.state.target) {
|
||||
return <Preloader />;
|
||||
}
|
||||
|
||||
const label: string = this.state.target.label;
|
||||
const url = `${ this.state.url }${ this.state.target.value }`;
|
||||
|
||||
return (
|
||||
<main>
|
||||
<h3 className="claim">TREZOR Bridge. <span>Version 2.0.12</span></h3>
|
||||
@ -70,7 +83,7 @@ export default class InstallBridge extends Component {
|
||||
value={ this.state.target }
|
||||
onChange={ this.onChange.bind(this) }
|
||||
options={ installers } />
|
||||
<a href={ url } className="button">Download for { this.state.target.label }</a>
|
||||
<a href={ url } className="button">Download for { label }</a>
|
||||
</div>
|
||||
<p>Learn more about latest version in <a href="https://github.com/trezor/trezord-go/blob/master/CHANGELOG.md" className="green" target="_blank" rel="noreferrer noopener">Changelog</a></p>
|
||||
</main>
|
||||
|
@ -13,8 +13,9 @@ import Log from '../common/Log';
|
||||
// import { Notification } from '../common/Notification';
|
||||
import Notifications, { Notification } from '../common/Notification';
|
||||
|
||||
import type { Props } from './index';
|
||||
|
||||
const BrowserNotSupported = (props: any) => {
|
||||
const BrowserNotSupported = (props: {}): React$Element<string> => {
|
||||
return (
|
||||
<main>
|
||||
<h2>Your browser is not supported</h2>
|
||||
@ -33,7 +34,9 @@ const BrowserNotSupported = (props: any) => {
|
||||
)
|
||||
}
|
||||
|
||||
export default (props: any): any => {
|
||||
|
||||
|
||||
export default (props: Props) => {
|
||||
|
||||
const web3 = props.web3;
|
||||
const { devices, browserState, transport } = props.connect;
|
||||
@ -43,7 +46,7 @@ export default (props: any): any => {
|
||||
let notification = null;
|
||||
let body = null;
|
||||
let css: string = 'app landing';
|
||||
const bridgeRoute: boolean = props.router.location.params.hasOwnProperty('bridge');
|
||||
const bridgeRoute: boolean = props.router.location.state.hasOwnProperty('bridge');
|
||||
|
||||
if (localStorageError) {
|
||||
notification = (<Notification
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
import React from 'react';
|
||||
|
||||
export default (props: any): any => {
|
||||
export default (props: {}): React$Element<string> => {
|
||||
return (
|
||||
<section className="landing">
|
||||
localstorage ERROR
|
||||
|
@ -4,7 +4,7 @@
|
||||
import React from 'react';
|
||||
import Loader from '../common/LoaderCircle';
|
||||
|
||||
export default (props: any): any => {
|
||||
export default (props: {}): React$Element<string> => {
|
||||
return (
|
||||
<section className="landing">
|
||||
<Loader label="Loading" size="100" />
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
import React from 'react';
|
||||
|
||||
export default (props: any): any => {
|
||||
export default (props: {}): React$Element<string> => {
|
||||
return (
|
||||
<section className="landing">
|
||||
connect ERROR
|
||||
|
@ -7,7 +7,27 @@ import { connect } from 'react-redux';
|
||||
|
||||
import LandingPage from './LandingPage';
|
||||
|
||||
const mapStateToProps = (state, own) => {
|
||||
import type { MapStateToProps, MapDispatchToProps } from 'react-redux';
|
||||
import type { State, Dispatch } from '../../flowtype';
|
||||
|
||||
export type Props = {
|
||||
localStorage: any,
|
||||
modal: any,
|
||||
web3: any,
|
||||
wallet: any,
|
||||
connect: any,
|
||||
router: any
|
||||
}
|
||||
|
||||
type DispatchProps = {
|
||||
foo: () => string
|
||||
}
|
||||
|
||||
type OwnProps = {
|
||||
|
||||
}
|
||||
|
||||
const mapStateToProps: MapStateToProps<State, OwnProps, Props> = (state: State): Props => {
|
||||
return {
|
||||
localStorage: state.localStorage,
|
||||
modal: state.modal,
|
||||
@ -18,10 +38,10 @@ const mapStateToProps = (state, own) => {
|
||||
};
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
const mapDispatchToProps: MapDispatchToProps<Dispatch, OwnProps, DispatchProps> = (dispatch: Dispatch) => {
|
||||
return {
|
||||
|
||||
foo: ():string => { return "A"; }
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(LandingPage);
|
||||
export default connect(mapStateToProps, null)(LandingPage);
|
@ -2,8 +2,9 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import type { Props } from './index';
|
||||
|
||||
const Confirmation = (props): any => {
|
||||
const Confirmation = (props: Props) => {
|
||||
const {
|
||||
amount,
|
||||
address,
|
||||
|
@ -2,8 +2,9 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import type { Props } from './index';
|
||||
|
||||
const InvalidPin = (props): any => {
|
||||
const InvalidPin = (props: Props) => {
|
||||
const { device } = props.modal;
|
||||
return (
|
||||
<div className="pin">
|
||||
|
@ -5,6 +5,7 @@ import React, { Component } from 'react';
|
||||
import raf from 'raf';
|
||||
import { findSelectedDevice } from '../../reducers/TrezorConnectReducer';
|
||||
|
||||
import type { Props } from './index';
|
||||
type State = {
|
||||
deviceLabel: string;
|
||||
singleInput: boolean;
|
||||
@ -17,13 +18,14 @@ type State = {
|
||||
visible: boolean;
|
||||
}
|
||||
|
||||
export default class PinModal extends Component {
|
||||
export default class PinModal extends Component<Props, State> {
|
||||
|
||||
keyboardHandler: (event: KeyboardEvent) => void;
|
||||
state: State;
|
||||
passphraseInput: HTMLInputElement;
|
||||
passphraseRevisionInput: HTMLInputElement;
|
||||
passphraseInput: ?HTMLInputElement;
|
||||
passphraseRevisionInput: ?HTMLInputElement;
|
||||
|
||||
constructor(props: any) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
// check if this device is already known
|
||||
@ -36,8 +38,6 @@ export default class PinModal extends Component {
|
||||
singleInput = selected.remember;
|
||||
}
|
||||
|
||||
console.warn("-----PASSS", selected)
|
||||
|
||||
this.state = {
|
||||
deviceLabel,
|
||||
singleInput,
|
||||
@ -72,7 +72,8 @@ export default class PinModal extends Component {
|
||||
|
||||
componentDidMount(): void {
|
||||
// one time autofocus
|
||||
this.passphraseInput.focus();
|
||||
if (this.passphraseInput)
|
||||
this.passphraseInput.focus();
|
||||
this.keyboardHandler = this.keyboardHandler.bind(this);
|
||||
window.addEventListener('keydown', this.keyboardHandler, false);
|
||||
|
||||
@ -117,9 +118,10 @@ export default class PinModal extends Component {
|
||||
passphraseRevisionInputValue = passphraseRevision.replace(/./g, '•');
|
||||
}
|
||||
|
||||
this.passphraseInput.value = passphraseInputValue;
|
||||
this.passphraseInput.setAttribute("type", visible ? "text" : "password");
|
||||
|
||||
if (this.passphraseInput) {
|
||||
this.passphraseInput.value = passphraseInputValue;
|
||||
this.passphraseInput.setAttribute("type", visible ? "text" : "password");
|
||||
}
|
||||
if (this.passphraseRevisionInput) {
|
||||
this.passphraseRevisionInput.value = passphraseRevisionInputValue;
|
||||
this.passphraseRevisionInput.setAttribute("type", visible ? "text" : "password");
|
||||
@ -207,28 +209,8 @@ export default class PinModal extends Component {
|
||||
|
||||
render(): any {
|
||||
|
||||
const {
|
||||
//onPassphraseChange,
|
||||
//onPassphraseSubmit,
|
||||
//onPassphraseSubmitEmpty,
|
||||
//onPassphraseForget,
|
||||
//onPassphraseFocus,
|
||||
//onPassphraseBlur,
|
||||
//onPassphraseSave,
|
||||
//onPassphraseShow,
|
||||
//onPassphraseHide
|
||||
} = this.props.modalActions;
|
||||
|
||||
const {
|
||||
device,
|
||||
//passphrase,
|
||||
//passphraseRevision,
|
||||
//passphraseFocused,
|
||||
//passphraseRevisionFocused,
|
||||
//passphraseVisible,
|
||||
//passphraseMatch,
|
||||
//passphraseRevisionTouched,
|
||||
passphraseCached
|
||||
} = this.props.modal;
|
||||
|
||||
const {
|
||||
|
@ -3,9 +3,7 @@
|
||||
|
||||
import React from 'react';
|
||||
|
||||
const Confirmation = (props): any => {
|
||||
|
||||
|
||||
const Confirmation = () => {
|
||||
return (
|
||||
<div className="confirm-tx">
|
||||
<div className="header">
|
||||
|
@ -1,17 +1,19 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
import React, { Component, KeyboardEvent } from 'react';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import type { Props } from './index';
|
||||
type State = {
|
||||
pin: string;
|
||||
}
|
||||
|
||||
export default class Pin extends Component {
|
||||
export default class Pin extends Component<Props, State> {
|
||||
|
||||
keyboardHandler: (event: KeyboardEvent) => void;
|
||||
state: State;
|
||||
|
||||
constructor(props: any) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
@ -36,7 +38,7 @@ export default class Pin extends Component {
|
||||
}
|
||||
|
||||
keyboardHandler(event: KeyboardEvent): void {
|
||||
const { onPinAdd, onPinBackspace, onPinSubmit } = this.props.modalActions;
|
||||
const { onPinSubmit } = this.props.modalActions;
|
||||
const { pin } = this.state;
|
||||
|
||||
event.preventDefault();
|
||||
|
@ -4,20 +4,18 @@
|
||||
import React, { Component } from 'react';
|
||||
import Loader from '../common/LoaderCircle';
|
||||
|
||||
type Props = {
|
||||
modal: any;
|
||||
}
|
||||
import type { Props } from './index';
|
||||
|
||||
type State = {
|
||||
+countdown: number;
|
||||
countdown: number;
|
||||
ticker?: number;
|
||||
}
|
||||
|
||||
export default class RememberDevice extends Component {
|
||||
export default class RememberDevice extends Component<Props, State> {
|
||||
|
||||
state: State;
|
||||
|
||||
constructor(props: any) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
@ -79,7 +77,7 @@ export default class RememberDevice extends Component {
|
||||
<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>
|
||||
<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.toString() } /></span></button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -10,8 +10,8 @@ import { CSSTransition, Transition } from 'react-transition-group';
|
||||
|
||||
import { UI } from 'trezor-connect';
|
||||
|
||||
import * as ModalActions from '../../actions/ModalActions';
|
||||
import * as ReceiveActions from '../../actions/ReceiveActions';
|
||||
import { default as ModalActions } from '../../actions/ModalActions';
|
||||
import { default as ReceiveActions } from '../../actions/ReceiveActions';
|
||||
|
||||
import Pin from './Pin';
|
||||
import InvalidPin from './InvalidPin';
|
||||
@ -26,6 +26,28 @@ import * as RECEIVE from '../../actions/constants/receive';
|
||||
import * as MODAL from '../../actions/constants/modal';
|
||||
import * as CONNECT from '../../actions/constants/TrezorConnect';
|
||||
|
||||
import type { MapStateToProps, MapDispatchToProps } from 'react-redux';
|
||||
import type { State, Dispatch } from '../../flowtype';
|
||||
|
||||
type OwnProps = { }
|
||||
|
||||
type StateProps = {
|
||||
modal: $ElementType<State, 'modal'>,
|
||||
accounts: $ElementType<State, 'accounts'>,
|
||||
devices: $PropertyType<$ElementType<State, 'connect'>, 'devices'>,
|
||||
connect: $ElementType<State, 'connect'>,
|
||||
sendForm: $ElementType<State, 'sendForm'>,
|
||||
receive: $ElementType<State, 'receive'>,
|
||||
localStorage: $ElementType<State, 'localStorage'>,
|
||||
}
|
||||
|
||||
type DispatchProps = {
|
||||
modalActions: typeof ModalActions,
|
||||
receiveActions: typeof ReceiveActions,
|
||||
}
|
||||
|
||||
export type Props = StateProps & DispatchProps;
|
||||
|
||||
const duration = 300;
|
||||
|
||||
|
||||
@ -38,7 +60,7 @@ const Fade = ({ children, ...props }) => (
|
||||
</CSSTransition>
|
||||
);
|
||||
|
||||
class Modal extends Component {
|
||||
class Modal extends Component<Props> {
|
||||
render() {
|
||||
const { opened, windowType } = this.props.modal;
|
||||
|
||||
@ -100,7 +122,7 @@ class Modal extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: any, own: any): any => {
|
||||
const mapStateToProps: MapStateToProps<State, OwnProps, StateProps> = (state: State, own: OwnProps): StateProps => {
|
||||
return {
|
||||
modal: state.modal,
|
||||
accounts: state.accounts,
|
||||
@ -112,7 +134,7 @@ const mapStateToProps = (state: any, own: any): any => {
|
||||
};
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch: any): any => {
|
||||
const mapDispatchToProps: MapDispatchToProps<Dispatch, OwnProps, DispatchProps> = (dispatch: Dispatch): DispatchProps => {
|
||||
return {
|
||||
modalActions: bindActionCreators(ModalActions, dispatch),
|
||||
receiveActions: bindActionCreators(ReceiveActions, dispatch),
|
||||
|
@ -7,7 +7,13 @@ import { connect } from 'react-redux';
|
||||
import { Notification } from '../common/Notification';
|
||||
import * as TrezorConnectActions from '../../actions/TrezorConnectActions';
|
||||
|
||||
const Acquire = (props: any): any => {
|
||||
import type { State, Dispatch } from '../../flowtype';
|
||||
type Props = {
|
||||
connect: $ElementType<State, 'connect'>,
|
||||
acquireDevice: typeof TrezorConnectActions.acquire
|
||||
}
|
||||
|
||||
const Acquire = (props: Props) => {
|
||||
|
||||
const actions = [
|
||||
{
|
||||
@ -26,22 +32,20 @@ const Acquire = (props: any): any => {
|
||||
className="info"
|
||||
cancelable={ false }
|
||||
actions={ actions }
|
||||
close={ () => {} }
|
||||
/>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, own) => {
|
||||
return {
|
||||
connect: state.connect
|
||||
};
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
acquireDevice: bindActionCreators(TrezorConnectActions.acquire, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Acquire);
|
||||
export default connect(
|
||||
(state: State) => {
|
||||
return {
|
||||
log: state.log
|
||||
};
|
||||
},
|
||||
(dispatch: Dispatch) => {
|
||||
return {
|
||||
toggle: bindActionCreators(TrezorConnectActions.acquire, dispatch),
|
||||
};
|
||||
}
|
||||
)(Acquire);
|
||||
|
@ -5,7 +5,7 @@ import React from 'react';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
const Bootloader = (props: any): any => {
|
||||
const Bootloader = () => {
|
||||
return (
|
||||
<section className="acquire">
|
||||
<h3>Bootloader mode</h3>
|
||||
@ -13,15 +13,4 @@ const Bootloader = (props: any): any => {
|
||||
);
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, own) => {
|
||||
return {
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Bootloader);
|
||||
export default connect(null, null)(Bootloader);
|
||||
|
@ -5,7 +5,7 @@ import React from 'react';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
const Dashboard = (props: any): any => {
|
||||
const Dashboard = () => {
|
||||
return (
|
||||
<section className="dashboard">
|
||||
<h2>Dashboard</h2>
|
||||
@ -18,15 +18,4 @@ const Dashboard = (props: any): any => {
|
||||
);
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, own) => {
|
||||
return {
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Dashboard);
|
||||
export default connect(null, null)(Dashboard);
|
||||
|
@ -5,7 +5,7 @@ import React from 'react';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
export const DeviceSettings = (props: any): any => {
|
||||
export const DeviceSettings = () => {
|
||||
return (
|
||||
<section className="settings">
|
||||
Device settings
|
||||
@ -13,15 +13,4 @@ export const DeviceSettings = (props: any): any => {
|
||||
);
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, own) => {
|
||||
return {
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(DeviceSettings);
|
||||
export default connect(null, null)(DeviceSettings);
|
||||
|
@ -1,77 +0,0 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
const formatTime = (ts) => {
|
||||
var date = new Date(ts * 1000);
|
||||
// Hours part from the timestamp
|
||||
var hours = date.getHours();
|
||||
// Minutes part from the timestamp
|
||||
var minutes = "0" + date.getMinutes();
|
||||
// Seconds part from the timestamp
|
||||
var seconds = "0" + date.getSeconds();
|
||||
|
||||
// Will display time in 10:30:23 format
|
||||
return hours + ':' + minutes.substr(-2) + ':' + seconds.substr(-2);
|
||||
}
|
||||
|
||||
const History = (props): any => {
|
||||
|
||||
const web3 = props.web3;
|
||||
const { addresses } = props.addresses;
|
||||
const currentAddress = addresses[ parseInt(props.match.params.address) ];
|
||||
|
||||
if (!currentAddress) return null;
|
||||
|
||||
let txs = null;
|
||||
let pendingTransactions = null;
|
||||
|
||||
if (currentAddress.history) {
|
||||
|
||||
const pending = currentAddress.pendingTx;
|
||||
|
||||
if (pending.length > 0) {
|
||||
pendingTransactions = pending.map((tx, i) => {
|
||||
|
||||
const etherscanLink = `https://ropsten.etherscan.io/tx/${ tx.hash }`;
|
||||
|
||||
return (
|
||||
<div key={i} className="history-pending-transaction">
|
||||
<a href={ etherscanLink } target="_blank" rel="noreferrer noopener">Details</a>
|
||||
<span className="address">{ tx.to }</span>
|
||||
Pending...
|
||||
</div>
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
txs = currentAddress.history.map((tx, i) => {
|
||||
const etherscanLink = `https://ropsten.etherscan.io/tx/${ tx.hash }`;
|
||||
return (
|
||||
<div key={i} className={ `history-transaction ${ tx.type }` }>
|
||||
<a href={ etherscanLink } target="_blank">Details</a>
|
||||
<span className="time">{ formatTime( parseInt(tx.timeStamp) ) }</span>
|
||||
<span className="address">{ tx.address }</span>
|
||||
<span className="amount">{ web3.fromWei(tx.value, 'ether') }</span>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<section className="history">
|
||||
{ pendingTransactions ?
|
||||
<div>
|
||||
<h2>Pending:</h2>
|
||||
{ pendingTransactions }
|
||||
</div>
|
||||
: null}
|
||||
|
||||
<h3>HISTORY OF { currentAddress.address }</h3>
|
||||
{ txs }
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export default History;
|
@ -10,16 +10,43 @@ import { QRCode } from 'react-qr-svg';
|
||||
|
||||
import AbstractAccount from './account/AbstractAccount';
|
||||
import { Notification } from '../common/Notification';
|
||||
import * as ReceiveActions from '../../actions/ReceiveActions';
|
||||
import * as AbstractAccountActions from '../../actions/AbstractAccountActions';
|
||||
import { default as ReceiveActions } from '../../actions/ReceiveActions';
|
||||
import { default as AbstractAccountActions } from '../../actions/AbstractAccountActions';
|
||||
|
||||
class Receive extends AbstractAccount {
|
||||
import type { MapStateToProps, MapDispatchToProps } from 'react-redux';
|
||||
import type { State, Dispatch } from '../../flowtype';
|
||||
import type { StateProps as BaseStateProps, DispatchProps as BaseDispatchProps, Props as BaseProps} from './account/AbstractAccount';
|
||||
|
||||
import type { AccountState } from './account/AbstractAccount';
|
||||
|
||||
type OwnProps = { }
|
||||
|
||||
type StateProps = StateProps & {
|
||||
receive: $ElementType<State, 'receive'>,
|
||||
}
|
||||
|
||||
type DispatchProps = BaseDispatchProps & {
|
||||
showAddress: typeof ReceiveActions.showAddress
|
||||
}
|
||||
|
||||
type Props = BaseProps & StateProps & DispatchProps;
|
||||
|
||||
|
||||
class Receive extends AbstractAccount<Props> {
|
||||
render() {
|
||||
return super.render() || _render(this.props, this.device, this.account, this.deviceStatusNotification);
|
||||
return super.render() || _render(this.props, this.state);
|
||||
}
|
||||
}
|
||||
|
||||
const _render = (props: any, device, account, deviceStatusNotification): any => {
|
||||
const _render = (props: Props, state: AccountState): React$Element<string> => {
|
||||
|
||||
const {
|
||||
device,
|
||||
account,
|
||||
deviceStatusNotification
|
||||
} = state;
|
||||
|
||||
if (!device || !account) return <section></section>;
|
||||
|
||||
const {
|
||||
addressVerified,
|
||||
@ -84,10 +111,9 @@ const _render = (props: any, device, account, deviceStatusNotification): any =>
|
||||
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, own) => {
|
||||
const mapStateToProps: MapStateToProps<State, OwnProps, StateProps> = (state: State, own: OwnProps): StateProps => {
|
||||
return {
|
||||
abstractAccount: state.abstractAccount,
|
||||
location: state.router.location,
|
||||
devices: state.connect.devices,
|
||||
accounts: state.accounts,
|
||||
discovery: state.discovery,
|
||||
@ -95,8 +121,8 @@ const mapStateToProps = (state, own) => {
|
||||
};
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
const mapDispatchToProps: MapDispatchToProps<Dispatch, OwnProps, DispatchProps> = (dispatch: Dispatch): DispatchProps => {
|
||||
return {
|
||||
abstractAccountActions: bindActionCreators(AbstractAccountActions, dispatch),
|
||||
initAccount: bindActionCreators(ReceiveActions.init, dispatch),
|
||||
updateAccount: bindActionCreators(ReceiveActions.update, dispatch),
|
||||
|
@ -5,7 +5,7 @@ import React from 'react';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
const SignVerify = (props: any): any => {
|
||||
const SignVerify = () => {
|
||||
return (
|
||||
<section className="signverify">
|
||||
<div className="sign">
|
||||
@ -30,15 +30,4 @@ const SignVerify = (props: any): any => {
|
||||
);
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, own) => {
|
||||
return {
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(SignVerify);
|
||||
export default connect(null, null)(SignVerify);
|
@ -5,7 +5,7 @@ import React from 'react';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
export const WalletSettings = (props: any): any => {
|
||||
export const WalletSettings = () => {
|
||||
return (
|
||||
<section className="settings">
|
||||
Wallet settings
|
||||
@ -13,15 +13,4 @@ export const WalletSettings = (props: any): any => {
|
||||
);
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, own) => {
|
||||
return {
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(WalletSettings);
|
||||
export default connect(null, null)(WalletSettings);
|
||||
|
@ -4,75 +4,103 @@
|
||||
import React, { Component } from 'react';
|
||||
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;
|
||||
// import * as AbstractAccountActions from '../../actions/AbstractAccountActions';
|
||||
import { default as AbstractAccountActions } from '../../../actions/AbstractAccountActions';
|
||||
|
||||
import type { State, TrezorDevice } from '../../../flowtype';
|
||||
import type { Account } from '../../../reducers/AccountsReducer';
|
||||
import type { Discovery } from '../../../reducers/DiscoveryReducer';
|
||||
|
||||
export type StateProps = {
|
||||
abstractAccount: $ElementType<State, 'abstractAccount'>,
|
||||
devices: $PropertyType<$ElementType<State, 'connect'>, 'devices'>,
|
||||
discovery: $ElementType<State, 'discovery'>,
|
||||
accounts: $ElementType<State, 'accounts'>,
|
||||
}
|
||||
|
||||
export default class AbstractAccount extends Component {
|
||||
export type DispatchProps = {
|
||||
abstractAccountActions: typeof AbstractAccountActions,
|
||||
initAccount: typeof AbstractAccountActions.init,
|
||||
updateAccount: typeof AbstractAccountActions.update,
|
||||
disposeAccount: typeof AbstractAccountActions.dispose,
|
||||
}
|
||||
|
||||
device: TrezorDevice;
|
||||
discovery: any;
|
||||
account: any;
|
||||
deviceStatusNotification: any;
|
||||
export type Props = StateProps & DispatchProps;
|
||||
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
this.state = {
|
||||
export type AccountState = {
|
||||
device: ?TrezorDevice;
|
||||
account: ?Account;
|
||||
discovery: ?Discovery;
|
||||
deviceStatusNotification: ?React$Element<typeof Notification>;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
export default class AbstractAccount<P> extends Component<Props & P, AccountState> {
|
||||
|
||||
setLocalVars(vars: any) {
|
||||
this.device = vars.device;
|
||||
this.discovery = vars.discovery;
|
||||
}
|
||||
state: AccountState = {
|
||||
device: null,
|
||||
account: null,
|
||||
discovery: null,
|
||||
deviceStatusNotification: null
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.props.abstractAccountActions.init();
|
||||
this.props.initAccount();
|
||||
}
|
||||
|
||||
componentWillUpdate(newProps: any) {
|
||||
this.device = null;
|
||||
this.discovery = null;
|
||||
this.account = null;
|
||||
this.deviceStatusNotification = null;
|
||||
|
||||
componentWillReceiveProps(props: Props & P) {
|
||||
this.props.abstractAccountActions.update();
|
||||
this.props.updateAccount();
|
||||
|
||||
const currentState = props.abstractAccount;
|
||||
|
||||
const device = findDevice(props.devices, currentState.deviceState, currentState.deviceId, currentState.deviceInstance);
|
||||
if (!device) return;
|
||||
const discovery = props.discovery.find(d => d.deviceState === device.state && d.network === currentState.network);
|
||||
const account = props.accounts.find(a => a.deviceState === currentState.deviceState && a.index === currentState.index && a.network === currentState.network);
|
||||
|
||||
let deviceStatusNotification: ?React$Element<typeof Notification> = null;
|
||||
if (account) {
|
||||
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" />;
|
||||
}
|
||||
}
|
||||
this.setState({
|
||||
device,
|
||||
discovery,
|
||||
account,
|
||||
deviceStatusNotification
|
||||
})
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.abstractAccountActions.dispose();
|
||||
this.props.disposeAccount();
|
||||
|
||||
this.device = null;
|
||||
this.discovery = null;
|
||||
this.account = null;
|
||||
this.deviceStatusNotification = null;
|
||||
}
|
||||
|
||||
render(): any {
|
||||
render(): ?React$Element<string> {
|
||||
|
||||
const props = this.props;
|
||||
const state = props.abstractAccount;
|
||||
const currentState = props.abstractAccount;
|
||||
|
||||
if (!state.deviceState) {
|
||||
if (!currentState.deviceState) {
|
||||
return (<section><Notification className="info" title="Loading device" /></section>);
|
||||
}
|
||||
|
||||
const {
|
||||
device,
|
||||
account,
|
||||
discovery
|
||||
} = this.state;
|
||||
|
||||
const device = findDevice(props.devices, state.deviceState, state.deviceId, state.deviceInstance);
|
||||
// const device = findDevice(props.devices, accountState.deviceState, accountState.deviceId, accountState.deviceInstance);
|
||||
|
||||
if (!device) {
|
||||
return (<section>Device with state {state.deviceState} not found</section>);
|
||||
return (<section>Device with state {currentState.deviceState} not found</section>);
|
||||
}
|
||||
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.index && a.network === state.network);
|
||||
let deviceStatusNotification = null;
|
||||
|
||||
if (!account) {
|
||||
if (!discovery || discovery.waitingForDevice) {
|
||||
@ -97,7 +125,11 @@ export default class AbstractAccount extends Component {
|
||||
} else {
|
||||
return (
|
||||
<section>
|
||||
<Notification className="info" title={ `Device ${ device.instanceLabel } is disconnected` } />
|
||||
<Notification
|
||||
className="info"
|
||||
title={ `Device ${ device.instanceLabel } is disconnected` }
|
||||
message="Connect to load accounts"
|
||||
/>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@ -114,20 +146,8 @@ export default class AbstractAccount extends Component {
|
||||
</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;
|
||||
}
|
||||
}
|
@ -4,13 +4,20 @@
|
||||
import React, { Component } from 'react';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
|
||||
type State = {
|
||||
style: any;
|
||||
|
||||
type Props = {
|
||||
pathname: string;
|
||||
}
|
||||
type State = {
|
||||
style: {
|
||||
width: number,
|
||||
left: number
|
||||
};
|
||||
}
|
||||
|
||||
class Indicator extends Component {
|
||||
class Indicator extends Component<Props, State> {
|
||||
|
||||
reposition: () => void;
|
||||
state: State;
|
||||
|
||||
constructor(props: any) {
|
||||
@ -45,7 +52,9 @@ class Indicator extends Component {
|
||||
|
||||
reposition() {
|
||||
const tabs = document.querySelector('.account-tabs');
|
||||
if (!tabs) return;
|
||||
const active = tabs.querySelector('.active');
|
||||
if (!active) return;
|
||||
const bounds = active.getBoundingClientRect();
|
||||
|
||||
const left = bounds.left - tabs.getBoundingClientRect().left;
|
||||
|
@ -10,27 +10,30 @@ import { findSelectedDevice } from '../../../reducers/TrezorConnectReducer';
|
||||
import Loader from '../../common/LoaderCircle';
|
||||
import Tooltip from 'rc-tooltip';
|
||||
|
||||
import type { Props } from './index';
|
||||
import type { TrezorDevice } from '../../../flowtype';
|
||||
|
||||
const AccountSelection = (props: any): any => {
|
||||
const AccountSelection = (props: Props): ?React$Element<string> => {
|
||||
|
||||
const selected = findSelectedDevice(props.connect);
|
||||
if (!selected) return null;
|
||||
|
||||
const { location } = props.router;
|
||||
const urlParams = location.params;
|
||||
const urlParams = location.state;
|
||||
const accounts = props.accounts;
|
||||
const baseUrl: string = urlParams.deviceInstance ? `/device/${urlParams.device}:${urlParams.deviceInstance}` : `/device/${urlParams.device}`;
|
||||
|
||||
const { config } = props.localStorage;
|
||||
const selectedCoin = config.coins.find(c => c.network === location.params.network);
|
||||
const selectedCoin = config.coins.find(c => c.network === location.state.network);
|
||||
if (!selectedCoin) return;
|
||||
|
||||
const fiatRate = props.fiat.find(f => f.network === selectedCoin.network);
|
||||
|
||||
// console.warn("AccountSelectionRender", selected, props);
|
||||
|
||||
const deviceAddresses: Array<any> = getAccounts(accounts, selected, location.params.network);
|
||||
const deviceAddresses: Array<any> = getAccounts(accounts, selected, location.state.network);
|
||||
let selectedAccounts = deviceAddresses.map((address, i) => {
|
||||
// const url: string = `${baseUrl}/network/${location.params.network}/address/${i}`;
|
||||
// const url: string = `${baseUrl}/network/${location.state.network}/address/${i}`;
|
||||
const url: string = location.pathname.replace(/address+\/([0-9]*)/, `address/${i}`);
|
||||
|
||||
let balance: string = 'Loading...';
|
||||
@ -65,7 +68,7 @@ const AccountSelection = (props: any): any => {
|
||||
}
|
||||
|
||||
let discoveryStatus = null;
|
||||
const discovery = props.discovery.find(d => d.deviceState === selected.state && d.network === location.params.network);
|
||||
const discovery = props.discovery.find(d => d.deviceState === selected.state && d.network === location.state.network);
|
||||
|
||||
if (discovery) {
|
||||
if (discovery.completed) {
|
||||
|
@ -1,7 +1,8 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
//import React, { Node } from 'react';
|
||||
import * as React from 'react';
|
||||
import { Link, NavLink } from 'react-router-dom';
|
||||
import { TransitionGroup, CSSTransition } from 'react-transition-group';
|
||||
|
||||
@ -11,7 +12,16 @@ import CoinSelection from './CoinSelection';
|
||||
import StickyContainer from './StickyContainer';
|
||||
import { findSelectedDevice } from '../../../reducers/TrezorConnectReducer';
|
||||
|
||||
const TransitionMenu = (props: any) => {
|
||||
import type { Props } from './index';
|
||||
import type { TrezorDevice } from '../../../flowtype';
|
||||
|
||||
|
||||
type TransitionMenuProps = {
|
||||
animationType: string;
|
||||
children?: React.Node;
|
||||
}
|
||||
|
||||
const TransitionMenu = (props: TransitionMenuProps): React$Element<TransitionGroup> => {
|
||||
return (
|
||||
<TransitionGroup component="div" className="transition-container">
|
||||
<CSSTransition
|
||||
@ -29,9 +39,9 @@ const TransitionMenu = (props: any) => {
|
||||
)
|
||||
}
|
||||
|
||||
const Aside = (props: any): any => {
|
||||
const Aside = (props: Props): React$Element<typeof StickyContainer | string> => {
|
||||
|
||||
const selected = findSelectedDevice(props.connect);
|
||||
const selected: ?TrezorDevice = findSelectedDevice(props.connect);
|
||||
const { location } = props.router;
|
||||
|
||||
if (location.pathname === '/' || !selected) return (<aside></aside>);
|
||||
@ -52,15 +62,15 @@ const Aside = (props: any): any => {
|
||||
|
||||
if (props.deviceDropdownOpened) {
|
||||
menu = <DeviceDropdown {...props} />;
|
||||
} else if (location.params.network) {
|
||||
} else if (location.state.network) {
|
||||
menu = (
|
||||
<TransitionMenu animationType={"slide-left"}>
|
||||
<TransitionMenu animationType={ "slide-left" }>
|
||||
<AccountSelection { ...props} />
|
||||
</TransitionMenu>
|
||||
);
|
||||
} else if (!selected.unacquired) {
|
||||
menu = (
|
||||
<TransitionMenu animationType={"slide-right"}>
|
||||
<TransitionMenu animationType={ "slide-right" }>
|
||||
<CoinSelection { ...props} />
|
||||
</TransitionMenu>
|
||||
);
|
||||
|
@ -4,7 +4,10 @@
|
||||
import React from 'react';
|
||||
import { Link, NavLink } from 'react-router-dom';
|
||||
|
||||
const CoinSelection = (props: any): any => {
|
||||
import type { Props } from './index';
|
||||
import type { TrezorDevice } from '../../../flowtype';
|
||||
|
||||
const CoinSelection = (props: Props): React$Element<string> => {
|
||||
const { location } = props.router;
|
||||
const { config } = props.localStorage;
|
||||
|
||||
|
@ -3,9 +3,12 @@
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import Select from 'react-select';
|
||||
import TrezorConnect from 'trezor-connect';
|
||||
|
||||
import { findSelectedDevice } from '../../../reducers/TrezorConnectReducer';
|
||||
|
||||
import type { Props } from './index';
|
||||
import type { TrezorDevice } from '../../../flowtype';
|
||||
|
||||
const Value = (props: any): any => {
|
||||
const device = props.value; // device is passed as value of selected item
|
||||
@ -96,52 +99,18 @@ const Value = (props: any): any => {
|
||||
);
|
||||
}
|
||||
|
||||
export const DeviceSelect1 = (props: any): any => {
|
||||
|
||||
const { devices } = props.connect;
|
||||
const selected = findSelectedDevice(props.connect);
|
||||
if (!selected) return null;
|
||||
|
||||
const handleMenuClick = (type, device) => {
|
||||
console.log("handleMenuClick", type, device)
|
||||
if (type === 'acquire') {
|
||||
props.acquireDevice(device);
|
||||
} else if (type === 'forget') {
|
||||
props.forgetDevice(device);
|
||||
}else if (type === 'settings') {
|
||||
props.duplicateDevice(device);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Select
|
||||
className="device-select"
|
||||
// disabled={ (devices && devices.length <= 1) }
|
||||
disabled={ false }
|
||||
searchable={ false }
|
||||
clearable= { false }
|
||||
tabSelectsValue={ false }
|
||||
valueComponent={ Value }
|
||||
onValueClick={ handleMenuClick }
|
||||
value={ selected }
|
||||
options={ [ ] }
|
||||
onOpen={ () => props.toggleDeviceDropdown(true) }
|
||||
onClose={ () => props.toggleDeviceDropdown(false) }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export const DeviceSelect = (props: any): any => {
|
||||
export const DeviceSelect = (props: Props) => {
|
||||
|
||||
const { devices, transport } = props.connect;
|
||||
const selected = findSelectedDevice(props.connect);
|
||||
const selected: ?TrezorDevice = findSelectedDevice(props.connect);
|
||||
if (!selected) return null;
|
||||
|
||||
const handleMenuClick = (type, device) => {
|
||||
console.log("handleMenuClick", type, device)
|
||||
if (type === 'acquire') {
|
||||
props.acquireDevice(device);
|
||||
props.acquireDevice();
|
||||
} else if (type === 'forget') {
|
||||
props.forgetDevice(device);
|
||||
}else if (type === 'settings') {
|
||||
@ -164,9 +133,17 @@ export const DeviceSelect = (props: any): any => {
|
||||
);
|
||||
}
|
||||
|
||||
export class DeviceDropdown extends Component {
|
||||
type DeviceMenuItem = {
|
||||
type: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
export class DeviceDropdown extends Component<Props> {
|
||||
|
||||
mouseDownHandler: (event: MouseEvent) => void;
|
||||
blurHandler: (event: FocusEvent) => void;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.mouseDownHandler = this.mouseDownHandler.bind(this);
|
||||
this.blurHandler = this.blurHandler.bind(this);
|
||||
@ -179,7 +156,7 @@ export class DeviceDropdown extends Component {
|
||||
}
|
||||
|
||||
mouseDownHandler(event: MouseEvent): void {
|
||||
let elem = event.target;
|
||||
let elem: any = (event.target : any);
|
||||
let block: boolean = false;
|
||||
while (elem.parentElement) {
|
||||
// if (elem.className.indexOf('aside-button') >= 0) {
|
||||
@ -212,9 +189,9 @@ export class DeviceDropdown extends Component {
|
||||
// window.removeEventListener('blur', this.blurHandler, false);
|
||||
}
|
||||
|
||||
onDeviceMenuClick(item, device): void {
|
||||
onDeviceMenuClick(item: DeviceMenuItem, device: TrezorDevice): void {
|
||||
if (item.type === 'reload') {
|
||||
this.props.acquireDevice(device);
|
||||
this.props.acquireDevice();
|
||||
} else if (item.type === 'forget') {
|
||||
// this.props.toggleDeviceDropdown(false);
|
||||
this.props.forgetDevice(device);
|
||||
@ -229,7 +206,8 @@ export class DeviceDropdown extends Component {
|
||||
render() {
|
||||
|
||||
const { devices, transport } = this.props.connect;
|
||||
const selected = findSelectedDevice(this.props.connect);
|
||||
const selected: ?TrezorDevice = findSelectedDevice(this.props.connect);
|
||||
if (!selected) return;
|
||||
|
||||
let webUsbButton = null;
|
||||
if (transport && transport.version.indexOf('webusb') >= 0) {
|
||||
@ -238,7 +216,7 @@ export class DeviceDropdown extends Component {
|
||||
|
||||
let currentDeviceMenu = null;
|
||||
if (selected.features) {
|
||||
const deviceMenuItems: Array<any> = [];
|
||||
const deviceMenuItems: Array<DeviceMenuItem> = [];
|
||||
|
||||
if (selected.isUsedElsewhere) {
|
||||
deviceMenuItems.push({ type: "reload", label: "Renew session" });
|
||||
@ -247,7 +225,7 @@ export class DeviceDropdown extends Component {
|
||||
}
|
||||
|
||||
deviceMenuItems.push({ type: "settings", label: "Device settings" });
|
||||
if (selected.features.passphrase_protection && selected.connected && selected.available) {
|
||||
if (selected.features && selected.features.passphrase_protection && selected.connected && selected.available) {
|
||||
deviceMenuItems.push({ type: "clone", label: "Clone device" });
|
||||
}
|
||||
if (selected.remember) {
|
||||
@ -257,7 +235,7 @@ export class DeviceDropdown extends Component {
|
||||
|
||||
const deviceMenuButtons = deviceMenuItems.map((item, index) => {
|
||||
return (
|
||||
<div key={ item.type } className={ item.type } onClick={ event => this.onDeviceMenuClick(item, selected) }>{ item.label}</div>
|
||||
<div key={ item.type } className={ item.type } onClick={ (event) => this.onDeviceMenuClick(item, selected) }>{ item.label}</div>
|
||||
)
|
||||
});
|
||||
currentDeviceMenu = deviceMenuButtons.length < 1 ? null : (
|
||||
|
@ -8,7 +8,13 @@ import raf from 'raf';
|
||||
import { DeviceSelect } from './DeviceSelection';
|
||||
import { getViewportHeight, getScrollY } from '../../../utils/windowUtils';
|
||||
|
||||
export default class StickyContainer extends PureComponent {
|
||||
type Props = {
|
||||
location: any,
|
||||
devices: any,
|
||||
children: any,
|
||||
}
|
||||
|
||||
export default class StickyContainer extends PureComponent<Props> {
|
||||
|
||||
// Class variables.
|
||||
currentScrollY: number = 0;
|
||||
@ -18,15 +24,15 @@ export default class StickyContainer extends PureComponent {
|
||||
framePending: boolean = false;
|
||||
stickToBottom: boolean = false;
|
||||
top: number = 0;
|
||||
aside;
|
||||
wrapper;
|
||||
aside: ?HTMLElement;
|
||||
wrapper: ?HTMLElement;
|
||||
subscribers = [];
|
||||
|
||||
handleResize = event => {
|
||||
handleResize = (event: Event) => {
|
||||
|
||||
}
|
||||
|
||||
handleScroll = event => {
|
||||
handleScroll = (event: ?Event) => {
|
||||
if (!this.framePending) {
|
||||
this.framePending = true;
|
||||
raf(this.update);
|
||||
@ -34,24 +40,27 @@ export default class StickyContainer extends PureComponent {
|
||||
}
|
||||
|
||||
shouldUpdate = () => {
|
||||
if (!this.wrapper) return;
|
||||
const wrapper: ?HTMLElement = this.wrapper;
|
||||
const aside: ?HTMLElement = this.aside;
|
||||
if (!wrapper || !aside) return;
|
||||
const helpButton: ?HTMLElement = wrapper.querySelector('.help');
|
||||
if (!helpButton) return;
|
||||
|
||||
|
||||
const viewportHeight = getViewportHeight();
|
||||
const helpButton = this.wrapper.querySelector('.help');
|
||||
const viewportHeight: number = getViewportHeight();
|
||||
const helpButtonBounds = helpButton.getBoundingClientRect();
|
||||
const asideBounds = this.aside.getBoundingClientRect();
|
||||
const wrapperBounds = this.wrapper.getBoundingClientRect();
|
||||
const asideBounds = aside.getBoundingClientRect();
|
||||
const wrapperBounds = wrapper.getBoundingClientRect();
|
||||
|
||||
const scrollDirection = this.currentScrollY >= this.lastKnownScrollY ? 'down' : 'up';
|
||||
const distanceScrolled = Math.abs(this.currentScrollY - this.lastKnownScrollY);
|
||||
|
||||
|
||||
if (asideBounds.top < 0) {
|
||||
this.wrapper.classList.add('fixed');
|
||||
let maxTop = 1;
|
||||
wrapper.classList.add('fixed');
|
||||
let maxTop : number= 1;
|
||||
if (wrapperBounds.height > viewportHeight) {
|
||||
const bottomOutOfBounds = (helpButtonBounds.bottom <= viewportHeight && scrollDirection === 'down');
|
||||
const topOutOfBounds = (wrapperBounds.top > 0 && scrollDirection === 'up');
|
||||
const bottomOutOfBounds: boolean = (helpButtonBounds.bottom <= viewportHeight && scrollDirection === 'down');
|
||||
const topOutOfBounds: boolean = (wrapperBounds.top > 0 && scrollDirection === 'up');
|
||||
if (!bottomOutOfBounds && !topOutOfBounds) {
|
||||
this.topOffset += scrollDirection === 'down' ? - distanceScrolled : distanceScrolled;
|
||||
}
|
||||
@ -60,27 +69,27 @@ export default class StickyContainer extends PureComponent {
|
||||
|
||||
if (this.topOffset > 0) this.topOffset = 0;
|
||||
if (maxTop < 0 && this.topOffset < maxTop) this.topOffset = maxTop;
|
||||
this.wrapper.style.top = `${this.topOffset}px`;
|
||||
wrapper.style.top = `${this.topOffset}px`;
|
||||
|
||||
} else {
|
||||
this.wrapper.classList.remove('fixed');
|
||||
this.wrapper.style.top = `0px`;
|
||||
wrapper.classList.remove('fixed');
|
||||
wrapper.style.top = `0px`;
|
||||
this.topOffset = 0;
|
||||
}
|
||||
|
||||
if (wrapperBounds.height > viewportHeight) {
|
||||
this.wrapper.classList.remove('fixed-bottom');
|
||||
wrapper.classList.remove('fixed-bottom');
|
||||
} else {
|
||||
if (this.wrapper.classList.contains('fixed-bottom')) {
|
||||
if (wrapper.classList.contains('fixed-bottom')) {
|
||||
if (helpButtonBounds.top < wrapperBounds.bottom - helpButtonBounds.height) {
|
||||
this.wrapper.classList.remove('fixed-bottom');
|
||||
wrapper.classList.remove('fixed-bottom');
|
||||
}
|
||||
} else if(helpButtonBounds.bottom < viewportHeight) {
|
||||
this.wrapper.classList.add('fixed-bottom');
|
||||
} else if (helpButtonBounds.bottom < viewportHeight) {
|
||||
wrapper.classList.add('fixed-bottom');
|
||||
}
|
||||
}
|
||||
|
||||
this.aside.style.minHeight = `${ wrapperBounds.height }px`;
|
||||
aside.style.minHeight = `${ wrapperBounds.height }px`;
|
||||
}
|
||||
|
||||
update = () => {
|
||||
@ -101,8 +110,8 @@ export default class StickyContainer extends PureComponent {
|
||||
window.removeEventListener('resize', this.handleScroll);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (this.props.location !== prevProps.location) {
|
||||
componentDidUpdate(prevProps: Props) {
|
||||
if (this.props.location !== prevProps.location && this.aside) {
|
||||
const asideBounds = this.aside.getBoundingClientRect();
|
||||
if (asideBounds.top < 0) {
|
||||
window.scrollTo(0, getScrollY() + asideBounds.top);
|
||||
|
@ -11,7 +11,36 @@ import { toggleDeviceDropdown } from '../../../actions/WalletActions';
|
||||
|
||||
import Aside from './Aside';
|
||||
|
||||
const mapStateToProps = (state, own) => {
|
||||
import type { MapStateToProps, MapDispatchToProps } from 'react-redux';
|
||||
import type { State, Dispatch } from '../../../flowtype';
|
||||
|
||||
type OwnProps = {
|
||||
|
||||
}
|
||||
|
||||
type StateProps = {
|
||||
connect: $ElementType<State, 'connect'>,
|
||||
accounts: $ElementType<State, 'accounts'>,
|
||||
router: $ElementType<State, 'router'>,
|
||||
deviceDropdownOpened: boolean,
|
||||
fiat: $ElementType<State, 'fiat'>,
|
||||
localStorage: $ElementType<State, 'localStorage'>,
|
||||
discovery: $ElementType<State, 'discovery'>,
|
||||
}
|
||||
|
||||
type DispatchProps = {
|
||||
toggleDeviceDropdown: typeof toggleDeviceDropdown,
|
||||
addAddress: typeof TrezorConnectActions.addAddress,
|
||||
acquireDevice: typeof TrezorConnectActions.acquire,
|
||||
forgetDevice: typeof TrezorConnectActions.forget,
|
||||
duplicateDevice: typeof TrezorConnectActions.duplicateDevice,
|
||||
gotoDeviceSettings: typeof TrezorConnectActions.gotoDeviceSettings,
|
||||
onSelectDevice: typeof TrezorConnectActions.onSelectDevice,
|
||||
}
|
||||
|
||||
export type Props = StateProps & DispatchProps;
|
||||
|
||||
const mapStateToProps: MapStateToProps<State, OwnProps, StateProps> = (state: State, own: OwnProps): StateProps => {
|
||||
return {
|
||||
connect: state.connect,
|
||||
accounts: state.accounts,
|
||||
@ -23,7 +52,7 @@ const mapStateToProps = (state, own) => {
|
||||
};
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
const mapDispatchToProps: MapDispatchToProps<Dispatch, OwnProps, DispatchProps> = (dispatch: Dispatch): DispatchProps => {
|
||||
return {
|
||||
//onAccountSelect: bindActionCreators(AccountActions.onAccountSelect, dispatch),
|
||||
toggleDeviceDropdown: bindActionCreators(toggleDeviceDropdown, dispatch),
|
||||
@ -36,7 +65,7 @@ const mapDispatchToProps = (dispatch) => {
|
||||
};
|
||||
}
|
||||
|
||||
//export default connect(mapStateToProps, mapDispatchToProps)(AddressMenu);
|
||||
// export default connect(mapStateToProps, mapDispatchToProps)(Aside);
|
||||
export default withRouter(
|
||||
connect(mapStateToProps, mapDispatchToProps)(Aside)
|
||||
);
|
@ -1,7 +1,7 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import * as React from 'react';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import { Route, withRouter } from 'react-router-dom';
|
||||
@ -14,7 +14,13 @@ import ModalContainer from '../modal';
|
||||
import Notifications from '../common/Notification';
|
||||
import Log from '../common/Log';
|
||||
|
||||
const Content = (props) => {
|
||||
import type { State, Dispatch } from '../../flowtype';
|
||||
|
||||
type Props = {
|
||||
children: React.Node
|
||||
}
|
||||
|
||||
const Content = (props: Props) => {
|
||||
return (
|
||||
<article>
|
||||
<nav>
|
||||
@ -28,7 +34,7 @@ const Content = (props) => {
|
||||
);
|
||||
}
|
||||
|
||||
const Wallet = (props: any): any => {
|
||||
const Wallet = (props: Props) => {
|
||||
return (
|
||||
<div className="app">
|
||||
<Header />
|
||||
@ -43,16 +49,6 @@ const Wallet = (props: any): any => {
|
||||
);
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, own) => {
|
||||
return {
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return { };
|
||||
}
|
||||
|
||||
export default withRouter(
|
||||
connect(mapStateToProps, mapDispatchToProps)(Wallet)
|
||||
connect(null, null)(Wallet)
|
||||
);
|
||||
|
@ -4,7 +4,9 @@
|
||||
import React from 'react';
|
||||
import Tooltip from 'rc-tooltip';
|
||||
|
||||
const AdvancedForm = (props: any): any => {
|
||||
import type { Props } from './index';
|
||||
|
||||
const AdvancedForm = (props: Props) => {
|
||||
|
||||
const { network } = props.abstractAccount;
|
||||
const {
|
||||
|
@ -1,33 +1,35 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import * as React from 'react';
|
||||
|
||||
type Props = {
|
||||
children: React.Node,
|
||||
className: string,
|
||||
isDisabled: boolean,
|
||||
isFocused: boolean,
|
||||
isSelected: boolean,
|
||||
onFocus: Function,
|
||||
onSelect: Function,
|
||||
option: any,
|
||||
}
|
||||
|
||||
// export default (props: any): any => {
|
||||
// console.log("RENDER CUSTOM OPTION", props)
|
||||
// return (
|
||||
// <div>1</div>
|
||||
// )
|
||||
// }
|
||||
|
||||
class FeeSelectOption extends Component {
|
||||
constructor(props) {
|
||||
export default class CoinSelectOption extends React.Component<Props> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
handleMouseDown(event) {
|
||||
handleMouseDown(event: MouseEvent) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.props.onSelect(this.props.option, event);
|
||||
}
|
||||
|
||||
handleMouseEnter(event) {
|
||||
handleMouseEnter(event: MouseEvent) {
|
||||
this.props.onFocus(this.props.option, event);
|
||||
}
|
||||
|
||||
handleMouseMove(event) {
|
||||
handleMouseMove(event: MouseEvent) {
|
||||
if (this.props.isFocused) return;
|
||||
this.props.onFocus(this.props.option, event);
|
||||
}
|
||||
@ -44,17 +46,4 @@ class FeeSelectOption extends Component {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
FeeSelectOption.propTypes = {
|
||||
children: PropTypes.node,
|
||||
className: PropTypes.string,
|
||||
isDisabled: PropTypes.bool,
|
||||
isFocused: PropTypes.bool,
|
||||
isSelected: PropTypes.bool,
|
||||
onFocus: PropTypes.func,
|
||||
onSelect: PropTypes.func,
|
||||
option: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default FeeSelectOption;
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import * as React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
|
||||
@ -16,22 +16,33 @@ export const FeeSelectValue = (props: any): any => {
|
||||
);
|
||||
}
|
||||
|
||||
export class FeeSelectOption extends Component {
|
||||
constructor(props) {
|
||||
type Props = {
|
||||
children: React.Node,
|
||||
className: string,
|
||||
isDisabled: boolean,
|
||||
isFocused: boolean,
|
||||
isSelected: boolean,
|
||||
onFocus: Function,
|
||||
onSelect: Function,
|
||||
option: any,
|
||||
}
|
||||
|
||||
export class FeeSelectOption extends React.Component<Props> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
handleMouseDown(event) {
|
||||
handleMouseDown(event: MouseEvent) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.props.onSelect(this.props.option, event);
|
||||
}
|
||||
|
||||
handleMouseEnter(event) {
|
||||
handleMouseEnter(event: MouseEvent) {
|
||||
this.props.onFocus(this.props.option, event);
|
||||
}
|
||||
|
||||
handleMouseMove(event) {
|
||||
handleMouseMove(event: MouseEvent) {
|
||||
if (this.props.isFocused) return;
|
||||
this.props.onFocus(this.props.option, event);
|
||||
}
|
||||
@ -48,16 +59,3 @@ export class FeeSelectOption extends Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
FeeSelectOption.propTypes = {
|
||||
children: PropTypes.node,
|
||||
className: PropTypes.string,
|
||||
isDisabled: PropTypes.bool,
|
||||
isFocused: PropTypes.bool,
|
||||
isSelected: PropTypes.bool,
|
||||
onFocus: PropTypes.func,
|
||||
onSelect: PropTypes.func,
|
||||
option: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,60 +0,0 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
|
||||
// export default (props: any): any => {
|
||||
// console.log("RENDER CUSTOM OPTION", props)
|
||||
// return (
|
||||
// <div>1</div>
|
||||
// )
|
||||
// }
|
||||
|
||||
class FeeSelectOption extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
handleMouseDown(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.props.onSelect(this.props.option, event);
|
||||
}
|
||||
|
||||
handleMouseEnter(event) {
|
||||
this.props.onFocus(this.props.option, event);
|
||||
}
|
||||
|
||||
handleMouseMove(event) {
|
||||
if (this.props.isFocused) return;
|
||||
this.props.onFocus(this.props.option, event);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className={ this.props.className }
|
||||
onMouseDown={ this.handleMouseDown.bind(this) }
|
||||
onMouseEnter={ this.handleMouseEnter.bind(this) }
|
||||
onMouseMove={ this.handleMouseMove.bind(this) }>
|
||||
<span className="fee-label">{ this.props.children }</span>
|
||||
|
||||
<span className="fee-value">$10.20 / 8.828392159996002 ETH</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
FeeSelectOption.propTypes = {
|
||||
children: PropTypes.node,
|
||||
className: PropTypes.string,
|
||||
isDisabled: PropTypes.bool,
|
||||
isFocused: PropTypes.bool,
|
||||
isSelected: PropTypes.bool,
|
||||
onFocus: PropTypes.func,
|
||||
onSelect: PropTypes.func,
|
||||
option: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default FeeSelectOption;
|
@ -5,9 +5,19 @@ import React from 'react';
|
||||
import ColorHash from 'color-hash';
|
||||
import ScaleText from 'react-scale-text';
|
||||
|
||||
const PendingTransactions = (props: any): any => {
|
||||
import type { Props as ParentProps } from './index';
|
||||
import type { Coin } from '../../../reducers/LocalStorageReducer';
|
||||
import type { Account } from '../../../reducers/AccountsReducer';
|
||||
|
||||
const account = props.accounts.find(a => a.deviceState === props.sendForm.deviceState && a.index === props.sendForm.accountIndex && a.network === props.sendForm.network);
|
||||
type Props = ParentProps & {
|
||||
account: Account,
|
||||
selectedCoin: Coin
|
||||
// account: any
|
||||
}
|
||||
|
||||
const PendingTransactions = (props: Props) => {
|
||||
|
||||
const account = props.account; //props.accounts.find(a => a.deviceState === props.sendForm.deviceState && a.index === props.sendForm.accountIndex && a.network === props.sendForm.network);
|
||||
const pending = props.pending.filter(p => p.network === account.network && p.address === account.address);
|
||||
|
||||
if (pending.length < 1) return null;
|
||||
|
@ -9,14 +9,25 @@ import { FeeSelectValue, FeeSelectOption } from './FeeSelect';
|
||||
import { Notification } from '../../common/Notification';
|
||||
import AbstractAccount from '../account/AbstractAccount';
|
||||
|
||||
export default class Send extends AbstractAccount {
|
||||
import type { Props } from './index';
|
||||
import type { AccountState } from '../account/AbstractAccount';
|
||||
|
||||
export default class Send extends AbstractAccount<Props> {
|
||||
render() {
|
||||
return super.render() || _render(this.props, this.device, this.discovery, this.account, this.deviceStatusNotification);
|
||||
return super.render() || _render(this.props, this.state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const _render = (props: any, device, discovery, account, deviceStatusNotification): any => {
|
||||
const _render = (props: Props, state: AccountState): React$Element<string> => {
|
||||
|
||||
const {
|
||||
device,
|
||||
account,
|
||||
deviceStatusNotification
|
||||
} = state;
|
||||
|
||||
if (!device || !account) return <section></section>;
|
||||
|
||||
const addressTokens = props.tokens.filter(t => t.ethAddress === account.address);
|
||||
const { network } = props.abstractAccount;
|
||||
@ -170,7 +181,10 @@ const _render = (props: any, device, discovery, account, deviceStatusNotificatio
|
||||
<button disabled={ buttonDisabled } onClick={ event => onSend() }>{ buttonLabel }</button>
|
||||
</AdvancedForm>
|
||||
|
||||
<PendingTransactions {...props} selectedCoin={selectedCoin} />
|
||||
<PendingTransactions
|
||||
{ ...props }
|
||||
account={ account }
|
||||
selectedCoin={ selectedCoin } />
|
||||
|
||||
</section>
|
||||
);
|
||||
|
@ -5,14 +5,35 @@ import React, { Component, PropTypes } from 'react';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import * as SendFormActions from '../../../actions/SendFormActions';
|
||||
import * as AbstractAccountActions from '../../../actions/AbstractAccountActions';
|
||||
import { default as SendFormActions } from '../../../actions/SendFormActions';
|
||||
import { default as AbstractAccountActions } from '../../../actions/AbstractAccountActions';
|
||||
import SendForm from './SendForm';
|
||||
|
||||
const mapStateToProps = (state, own) => {
|
||||
import type { MapStateToProps, MapDispatchToProps } from 'react-redux';
|
||||
import type { State, Dispatch } from '../../../flowtype';
|
||||
import type { StateProps as BaseStateProps, DispatchProps as BaseDispatchProps, Props as BaseProps} from '../account/AbstractAccount';
|
||||
|
||||
type OwnProps = { }
|
||||
|
||||
type StateProps = StateProps & {
|
||||
tokens: $ElementType<State, 'tokens'>,
|
||||
pending: $ElementType<State, 'pending'>,
|
||||
fiat: $ElementType<State, 'fiat'>,
|
||||
localStorage: $ElementType<State, 'localStorage'>,
|
||||
}
|
||||
|
||||
type DispatchProps = BaseDispatchProps & {
|
||||
initAccount: typeof SendFormActions.init,
|
||||
updateAccount: typeof SendFormActions.update,
|
||||
disposeAccount: typeof SendFormActions.dispose,
|
||||
sendFormActions: typeof SendFormActions
|
||||
}
|
||||
|
||||
export type Props = BaseProps & StateProps & DispatchProps;
|
||||
|
||||
const mapStateToProps: MapStateToProps<State, OwnProps, StateProps> = (state: State, own: OwnProps): StateProps => {
|
||||
return {
|
||||
abstractAccount: state.abstractAccount,
|
||||
location: state.router.location,
|
||||
devices: state.connect.devices,
|
||||
accounts: state.accounts,
|
||||
discovery: state.discovery,
|
||||
@ -24,9 +45,9 @@ const mapStateToProps = (state, own) => {
|
||||
};
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
const mapDispatchToProps: MapDispatchToProps<Dispatch, OwnProps, DispatchProps> = (dispatch: Dispatch): DispatchProps => {
|
||||
return {
|
||||
abstractAccountActions: bindActionCreators(AbstractAccountActions, dispatch),
|
||||
abstractAccountActions: bindActionCreators(AbstractAccountActions, dispatch),
|
||||
sendFormActions: bindActionCreators(SendFormActions, dispatch),
|
||||
initAccount: bindActionCreators(SendFormActions.init, dispatch),
|
||||
updateAccount: bindActionCreators(SendFormActions.update, dispatch),
|
||||
|
@ -11,14 +11,29 @@ import SummaryDetails from './SummaryDetails.js';
|
||||
import SummaryTokens from './SummaryTokens.js';
|
||||
import { findDevice } from '../../../utils/reducerUtils';
|
||||
|
||||
import type { Props } from './index';
|
||||
import type { AccountState } from '../account/AbstractAccount';
|
||||
|
||||
export default class Summary extends AbstractAccount {
|
||||
import type { TrezorDevice } from '../../../flowtype';
|
||||
import type { NetworkToken } from '../../../reducers/LocalStorageReducer';
|
||||
import type { Account } from '../../../reducers/AccountsReducer';
|
||||
import type { Discovery } from '../../../reducers/DiscoveryReducer';
|
||||
|
||||
export default class Summary extends AbstractAccount<Props> {
|
||||
render() {
|
||||
return super.render() || _render(this.props, this.device, this.discovery, this.account, this.deviceStatusNotification);
|
||||
return super.render() || _render(this.props, this.state);
|
||||
}
|
||||
}
|
||||
|
||||
const _render = (props: any, device, discovery, account, deviceStatusNotification): any => {
|
||||
const _render = (props: Props, state: AccountState): React$Element<string> => {
|
||||
|
||||
const {
|
||||
device,
|
||||
account,
|
||||
deviceStatusNotification
|
||||
} = state;
|
||||
|
||||
if (!device || !account) return <section></section>;
|
||||
|
||||
const abstractAccount = props.abstractAccount;
|
||||
const tokens = props.tokens.filter(t => t.ethAddress === account.address);
|
||||
@ -36,7 +51,7 @@ const _render = (props: any, device, discovery, account, deviceStatusNotificatio
|
||||
network={ abstractAccount.network }
|
||||
fiat={ props.fiat }
|
||||
localStorage={ props.localStorage }
|
||||
onToggle={ props.summaryActions.onDetailsToggle } />
|
||||
onToggle={ props.onDetailsToggle } />
|
||||
|
||||
<h2>Tokens</h2>
|
||||
{/* 0x58cda554935e4a1f2acbe15f8757400af275e084 */}
|
||||
@ -46,27 +61,28 @@ const _render = (props: any, device, discovery, account, deviceStatusNotificatio
|
||||
multi={ false }
|
||||
autoload={ false }
|
||||
ignoreCase={ true }
|
||||
backspaceRemoves={ true }
|
||||
value={ null }
|
||||
onChange={ token => props.addToken(token, account) }
|
||||
loadOptions={ input => props.loadTokens(input, account.network) }
|
||||
filterOptions= {
|
||||
(options, search, values) => {
|
||||
(options: Array<NetworkToken>, search: string, values) => {
|
||||
return options.filter(o => {
|
||||
return !tokens.find(t => t.symbol === o.symbol);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
value={ props.summary.selectedToken }
|
||||
onChange={ token => props.summaryActions.selectToken(token, account) }
|
||||
valueKey="symbol"
|
||||
labelKey="symbol"
|
||||
placeholder="Search for token"
|
||||
searchPromptText="Type token name or address"
|
||||
noResultsText="Token not found"
|
||||
loadOptions={ input => props.summaryActions.loadTokens(input, account) }
|
||||
backspaceRemoves={true} />
|
||||
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
<SummaryTokens tokens={ tokens } removeToken={ props.summaryActions.removeToken } />
|
||||
<SummaryTokens tokens={ tokens } removeToken={ props.removeToken } />
|
||||
|
||||
</section>
|
||||
|
||||
|
@ -4,7 +4,18 @@
|
||||
import React from 'react';
|
||||
import BigNumber from 'bignumber.js';
|
||||
|
||||
const SummaryDetails = (props: any): any => {
|
||||
import type { Props as BaseProps } from './index';
|
||||
|
||||
type Props = {
|
||||
summary: $ElementType<BaseProps, 'summary'>,
|
||||
balance: string,
|
||||
network: string,
|
||||
fiat: $ElementType<BaseProps, 'fiat'>,
|
||||
localStorage: $ElementType<BaseProps, 'localStorage'>,
|
||||
onToggle: $ElementType<BaseProps, 'onDetailsToggle'>
|
||||
}
|
||||
|
||||
const SummaryDetails = (props: Props): ?React$Element<string> => {
|
||||
|
||||
if (!props.summary.details) return (
|
||||
<div className="summary-details">
|
||||
|
@ -5,29 +5,36 @@ import React from 'react';
|
||||
import ColorHash from 'color-hash';
|
||||
import ScaleText from 'react-scale-text';
|
||||
|
||||
const SummaryTokens = (props: any): any => {
|
||||
import type { Token } from '../../../reducers/TokensReducer';
|
||||
|
||||
type Props = {
|
||||
tokens: Array<Token>,
|
||||
removeToken: (token: Token) => void
|
||||
}
|
||||
|
||||
const SummaryTokens = (props: Props) => {
|
||||
|
||||
if (!props.tokens || props.tokens.length < 1) return null;
|
||||
|
||||
const bgColor = new ColorHash({lightness: 0.7});
|
||||
const textColor = new ColorHash();
|
||||
|
||||
const tokens = props.tokens.map((t, i) => {
|
||||
const tokens = props.tokens.map((token, index) => {
|
||||
let iconColor = {
|
||||
color: textColor.hex(t.name),
|
||||
background: bgColor.hex(t.name),
|
||||
borderColor: bgColor.hex(t.name)
|
||||
color: textColor.hex(token.name),
|
||||
background: bgColor.hex(token.name),
|
||||
borderColor: bgColor.hex(token.name)
|
||||
}
|
||||
return (
|
||||
<div key={i} className="token">
|
||||
<div key={ index } className="token">
|
||||
<div className="icon" style={ iconColor }>
|
||||
<div className="icon-inner">
|
||||
<ScaleText widthOnly><p>{ t.symbol }</p></ScaleText>
|
||||
<ScaleText widthOnly><p>{ token.symbol }</p></ScaleText>
|
||||
</div>
|
||||
</div>
|
||||
<div className="name">{ t.name }</div>
|
||||
<div className="balance">{ t.balance } { t.symbol }</div>
|
||||
<button className="transparent" onClick={ event => props.removeToken(t) }></button>
|
||||
<div className="name">{ token.name }</div>
|
||||
<div className="balance">{ token.balance } { token.symbol }</div>
|
||||
<button className="transparent" onClick={ event => props.removeToken(token) }></button>
|
||||
</div>
|
||||
)
|
||||
});
|
||||
@ -37,7 +44,6 @@ const SummaryTokens = (props: any): any => {
|
||||
{ tokens }
|
||||
</div>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
export default SummaryTokens;
|
@ -6,32 +6,62 @@ import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import Summary from './Summary';
|
||||
import * as AbstractAccountActions from '../../../actions/AbstractAccountActions';
|
||||
import { default as AbstractAccountActions } from '../../../actions/AbstractAccountActions';
|
||||
import * as SummaryActions from '../../../actions/SummaryActions';
|
||||
import * as TokenActions from '../../../actions/TokenActions';
|
||||
|
||||
const mapStateToProps = (state, own) => {
|
||||
import type { ActionCreators } from 'redux';
|
||||
import type { MapStateToProps, MapDispatchToProps } from 'react-redux';
|
||||
import type { State, Dispatch } from '../../../flowtype';
|
||||
import type { StateProps as BaseStateProps, DispatchProps as BaseDispatchProps, Props as BaseProps} from '../account/AbstractAccount';
|
||||
|
||||
type OwnProps = { }
|
||||
|
||||
type StateProps = StateProps & {
|
||||
tokens: $ElementType<State, 'tokens'>,
|
||||
summary: $ElementType<State, 'summary'>,
|
||||
fiat: $ElementType<State, 'fiat'>,
|
||||
localStorage: $ElementType<State, 'localStorage'>,
|
||||
}
|
||||
|
||||
type DispatchProps = BaseDispatchProps & {
|
||||
initAccount: typeof SummaryActions.init,
|
||||
updateAccount: typeof SummaryActions.update,
|
||||
disposeAccount: typeof SummaryActions.dispose,
|
||||
onDetailsToggle: typeof SummaryActions.onDetailsToggle,
|
||||
addToken: typeof TokenActions.add,
|
||||
loadTokens: typeof TokenActions.load,
|
||||
removeToken: typeof TokenActions.remove,
|
||||
}
|
||||
|
||||
export type Props = BaseProps & StateProps & DispatchProps;
|
||||
|
||||
const mapStateToProps: MapStateToProps<State, OwnProps, StateProps> = (state: State, own: OwnProps): StateProps => {
|
||||
return {
|
||||
abstractAccount: state.abstractAccount,
|
||||
|
||||
location: state.router.location,
|
||||
devices: state.connect.devices,
|
||||
accounts: state.accounts,
|
||||
discovery: state.discovery,
|
||||
|
||||
tokens: state.tokens,
|
||||
|
||||
summary: state.summary,
|
||||
fiat: state.fiat,
|
||||
localStorage: state.localStorage
|
||||
localStorage: state.localStorage,
|
||||
};
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
const mapDispatchToProps: MapDispatchToProps<Dispatch, OwnProps, DispatchProps> = (dispatch: Dispatch): DispatchProps => {
|
||||
return {
|
||||
abstractAccountActions: bindActionCreators(AbstractAccountActions, dispatch),
|
||||
summaryActions: bindActionCreators(SummaryActions, dispatch),
|
||||
abstractAccountActions: bindActionCreators(AbstractAccountActions, dispatch),
|
||||
|
||||
initAccount: bindActionCreators(SummaryActions.init, dispatch),
|
||||
updateAccount: bindActionCreators(SummaryActions.update, dispatch),
|
||||
disposeAccount: bindActionCreators(SummaryActions.dispose, dispatch),
|
||||
|
||||
onDetailsToggle: bindActionCreators(SummaryActions.onDetailsToggle, dispatch),
|
||||
addToken: bindActionCreators(TokenActions.add, dispatch),
|
||||
loadTokens: bindActionCreators(TokenActions.load, dispatch),
|
||||
removeToken: bindActionCreators(TokenActions.remove, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,126 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
import type {
|
||||
Store as ReduxStore,
|
||||
StoreEnhancer as ReduxStoreEnhancer,
|
||||
Dispatch as ReduxDispatch,
|
||||
Middleware as ReduxMiddleware,
|
||||
MiddlewareAPI as ReduxMiddlewareAPI,
|
||||
ThunkAction as ReduxThunkAction,
|
||||
ThunkDispatch as ReduxThunkDispatch,
|
||||
PlainDispatch as ReduxPlainDispatch
|
||||
} from 'redux';
|
||||
|
||||
import type { Reducers, ReducersState } from '../reducers';
|
||||
|
||||
// Actions
|
||||
import type { AbstractAccountAction } from '../actions/AbstractAccountActions';
|
||||
import type { AddressAction } from '../actions/AddressActions';
|
||||
import type { DiscoveryAction } from '../actions/DiscoveryActions';
|
||||
import type { StorageAction } from '../actions/LocalStorageActions';
|
||||
import type { LogAction } from '../actions/LogActions';
|
||||
import type { ModalAction } from '../actions/ModalActions';
|
||||
import type { NotificationAction } from '../actions/NotificationActions';
|
||||
import type { ReceiveAction } from '../actions/ReceiveActions';
|
||||
import type { SendFormAction } from '../actions/SendFormActions';
|
||||
import type { SummaryAction } from '../actions/SummaryActions';
|
||||
import type { TokenAction } from '../actions/TokenActions';
|
||||
import type { TrezorConnectAction } from '../actions/TrezorConnectActions';
|
||||
import type { WalletAction } from '../actions/WalletActions';
|
||||
import type { Web3Action } from '../actions/Web3Actions';
|
||||
import type { FiatRateAction } from '../services/CoinmarketcapService'; // this service has no action file, all is written inside one file
|
||||
|
||||
import type {
|
||||
Device,
|
||||
Features,
|
||||
DeviceMessageType,
|
||||
TransportMessageType,
|
||||
UiMessageType,
|
||||
} from 'trezor-connect';
|
||||
|
||||
import type { RouterAction, LocationState } from 'react-router-redux';
|
||||
|
||||
export type TrezorDevice = {
|
||||
remember: boolean;
|
||||
connected: boolean;
|
||||
available: boolean; // device cannot be used because of features.passphrase_protection is different then expected (saved)
|
||||
path: string;
|
||||
label: string;
|
||||
state: ?string;
|
||||
instance?: number;
|
||||
instanceLabel: string;
|
||||
features?: Features;
|
||||
unacquired?: boolean;
|
||||
acquiring: boolean;
|
||||
isUsedElsewhere?: boolean;
|
||||
featuresNeedsReload?: boolean;
|
||||
ts: number;
|
||||
}
|
||||
|
||||
export type RouterLocationState = LocationState;
|
||||
|
||||
// Cast event from TrezorConnect event listener to react Action
|
||||
type DeviceEventAction = {
|
||||
type: DeviceMessageType,
|
||||
device: Device,
|
||||
}
|
||||
|
||||
type TransportEventAction = {
|
||||
type: TransportMessageType,
|
||||
payload: any,
|
||||
}
|
||||
|
||||
type UiEventAction = {
|
||||
type: UiMessageType,
|
||||
payload: any,
|
||||
}
|
||||
|
||||
// TODO: join this message with uiMessage
|
||||
type IFrameHandshake = {
|
||||
type: 'iframe_handshake',
|
||||
payload: any
|
||||
}
|
||||
|
||||
export type Action =
|
||||
RouterAction
|
||||
| IFrameHandshake
|
||||
| TransportEventAction
|
||||
| DeviceEventAction
|
||||
| UiEventAction
|
||||
|
||||
| AbstractAccountAction
|
||||
| AddressAction
|
||||
| DiscoveryAction
|
||||
| StorageAction
|
||||
| LogAction
|
||||
| ModalAction
|
||||
| NotificationAction
|
||||
| ReceiveAction
|
||||
| SendFormAction
|
||||
| SummaryAction
|
||||
| TokenAction
|
||||
| TrezorConnectAction
|
||||
| WalletAction
|
||||
| Web3Action
|
||||
| FiatRateAction;
|
||||
|
||||
export type State = ReducersState;
|
||||
|
||||
export type Accounts = $ElementType<State, 'accounts'>;
|
||||
export type LocalStorage = $ElementType<State, 'localStorage'>;
|
||||
export type Config = $PropertyType<$ElementType<State, 'localStorage'>, 'config'>;
|
||||
|
||||
|
||||
export type Dispatch = ReduxDispatch<State, Action>;
|
||||
export type MiddlewareDispatch = ReduxPlainDispatch<Action>;
|
||||
|
||||
export type MiddlewareAPI = ReduxMiddlewareAPI<State, Action>;
|
||||
export type Middleware = ReduxMiddleware<State, Action>;
|
||||
|
||||
export type Store = ReduxStore<State, Action>;
|
||||
export type StoreEnhancer = ReduxStoreEnhancer<State, Action>;
|
||||
|
||||
export type Dispatch = (action: Action | ThunkAction | PromiseAction) => any;
|
||||
export type GetState = () => State;
|
||||
export type ThunkAction = (dispatch: Dispatch, getState: GetState) => any;
|
||||
export type PromiseAction = Promise<Action>;
|
||||
|
||||
export type AsyncAction = ReduxThunkAction<State, Action>;
|
||||
|
132
src/js/flowtype/react-redux_v5.x.x.js
Normal file
132
src/js/flowtype/react-redux_v5.x.x.js
Normal file
@ -0,0 +1,132 @@
|
||||
// flow-typed signature: 59b0c4be0e1408f21e2446be96c79804
|
||||
// flow-typed version: 9092387fd2/react-redux_v5.x.x/flow_>=v0.54.x
|
||||
|
||||
import type { Dispatch, Store } from "redux";
|
||||
|
||||
declare module "react-redux" {
|
||||
/*
|
||||
|
||||
S = State
|
||||
A = Action
|
||||
OP = OwnProps
|
||||
SP = StateProps
|
||||
DP = DispatchProps
|
||||
|
||||
*/
|
||||
|
||||
declare type MapStateToProps<S, OP: Object, SP: Object> = (
|
||||
state: S,
|
||||
ownProps: OP
|
||||
) => ((state: S, ownProps: OP) => SP) | SP;
|
||||
|
||||
declare type MapDispatchToProps<A, OP: Object, DP: Object> =
|
||||
| ((dispatch: Dispatch<A>, ownProps: OP) => DP)
|
||||
| DP;
|
||||
|
||||
declare type MergeProps<SP, DP: Object, OP: Object, P: Object> = (
|
||||
stateProps: SP,
|
||||
dispatchProps: DP,
|
||||
ownProps: OP
|
||||
) => P;
|
||||
|
||||
declare type Context = { store: Store<*, *> };
|
||||
|
||||
declare type ComponentWithDefaultProps<DP: {}, P: {}, CP: P> = Class<
|
||||
React$Component<CP>
|
||||
> & { defaultProps: DP };
|
||||
|
||||
declare class ConnectedComponentWithDefaultProps<
|
||||
OP,
|
||||
DP,
|
||||
CP
|
||||
> extends React$Component<OP> {
|
||||
static defaultProps: DP, // <= workaround for https://github.com/facebook/flow/issues/4644
|
||||
static WrappedComponent: Class<React$Component<CP>>,
|
||||
getWrappedInstance(): React$Component<CP>,
|
||||
props: OP,
|
||||
state: void
|
||||
}
|
||||
|
||||
declare class ConnectedComponent<OP, P> extends React$Component<OP> {
|
||||
static WrappedComponent: Class<React$Component<P>>,
|
||||
getWrappedInstance(): React$Component<P>,
|
||||
props: OP,
|
||||
state: void
|
||||
}
|
||||
|
||||
declare type ConnectedComponentWithDefaultPropsClass<OP, DP, CP> = Class<
|
||||
ConnectedComponentWithDefaultProps<OP, DP, CP>
|
||||
>;
|
||||
|
||||
declare type ConnectedComponentClass<OP, P> = Class<
|
||||
ConnectedComponent<OP, P>
|
||||
>;
|
||||
|
||||
declare type Connector<OP, P> = (<DP: {}, CP: {}>(
|
||||
component: ComponentWithDefaultProps<DP, P, CP>
|
||||
) => ConnectedComponentWithDefaultPropsClass<OP, DP, CP>) &
|
||||
((component: React$ComponentType<P>) => ConnectedComponentClass<OP, P>);
|
||||
|
||||
declare class Provider<S, A> extends React$Component<{
|
||||
store: Store<S, A>,
|
||||
children?: any
|
||||
}> {}
|
||||
|
||||
declare function createProvider(
|
||||
storeKey?: string,
|
||||
subKey?: string
|
||||
): Provider<*, *>;
|
||||
|
||||
declare type ConnectOptions = {
|
||||
pure?: boolean,
|
||||
withRef?: boolean
|
||||
};
|
||||
|
||||
declare type Null = null | void;
|
||||
|
||||
declare function connect<A, OP>(
|
||||
...rest: Array<void> // <= workaround for https://github.com/facebook/flow/issues/2360
|
||||
): Connector<OP, $Supertype<{ dispatch: Dispatch<A> } & OP>>;
|
||||
|
||||
declare function connect<A, OP>(
|
||||
mapStateToProps: Null,
|
||||
mapDispatchToProps: Null,
|
||||
mergeProps: Null,
|
||||
options: ConnectOptions
|
||||
): Connector<OP, $Supertype<{ dispatch: Dispatch<A> } & OP>>;
|
||||
|
||||
declare function connect<S, A, OP, SP>(
|
||||
mapStateToProps: MapStateToProps<S, OP, SP>,
|
||||
mapDispatchToProps: Null,
|
||||
mergeProps: Null,
|
||||
options?: ConnectOptions
|
||||
): Connector<OP, $Supertype<SP & { dispatch: Dispatch<A> } & OP>>;
|
||||
|
||||
declare function connect<A, OP, DP>(
|
||||
mapStateToProps: Null,
|
||||
mapDispatchToProps: MapDispatchToProps<A, OP, DP>,
|
||||
mergeProps: Null,
|
||||
options?: ConnectOptions
|
||||
): Connector<OP, $Supertype<DP & OP>>;
|
||||
|
||||
declare function connect<S, A, OP, SP, DP>(
|
||||
mapStateToProps: MapStateToProps<S, OP, SP>,
|
||||
mapDispatchToProps: MapDispatchToProps<A, OP, DP>,
|
||||
mergeProps: Null,
|
||||
options?: ConnectOptions
|
||||
): Connector<OP, $Supertype<SP & DP & OP>>;
|
||||
|
||||
declare function connect<S, A, OP, SP, DP, P>(
|
||||
mapStateToProps: MapStateToProps<S, OP, SP>,
|
||||
mapDispatchToProps: Null,
|
||||
mergeProps: MergeProps<SP, DP, OP, P>,
|
||||
options?: ConnectOptions
|
||||
): Connector<OP, P>;
|
||||
|
||||
declare function connect<S, A, OP, SP, DP, P>(
|
||||
mapStateToProps: MapStateToProps<S, OP, SP>,
|
||||
mapDispatchToProps: MapDispatchToProps<A, OP, DP>,
|
||||
mergeProps: MergeProps<SP, DP, OP, P>,
|
||||
options?: ConnectOptions
|
||||
): Connector<OP, P>;
|
||||
}
|
157
src/js/flowtype/react-router-dom_v4.x.x.js
Normal file
157
src/js/flowtype/react-router-dom_v4.x.x.js
Normal file
@ -0,0 +1,157 @@
|
||||
declare module "react-router-dom" {
|
||||
declare export class BrowserRouter extends React$Component<{
|
||||
basename?: string,
|
||||
forceRefresh?: boolean,
|
||||
getUserConfirmation?: GetUserConfirmation,
|
||||
keyLength?: number,
|
||||
children?: React$Node
|
||||
}> {}
|
||||
|
||||
declare export class HashRouter extends React$Component<{
|
||||
basename?: string,
|
||||
getUserConfirmation?: GetUserConfirmation,
|
||||
hashType?: "slash" | "noslash" | "hashbang",
|
||||
children?: React$Node
|
||||
}> {}
|
||||
|
||||
declare export class Link extends React$Component<{
|
||||
className?: string,
|
||||
to: string | LocationShape,
|
||||
replace?: boolean,
|
||||
children?: React$Node
|
||||
}> {}
|
||||
|
||||
declare export class NavLink extends React$Component<{
|
||||
to: string | LocationShape,
|
||||
activeClassName?: string,
|
||||
className?: string,
|
||||
activeStyle?: Object,
|
||||
style?: Object,
|
||||
isActive?: (match: Match, location: Location) => boolean,
|
||||
children?: React$Node,
|
||||
exact?: boolean,
|
||||
strict?: boolean
|
||||
}> {}
|
||||
|
||||
// NOTE: Below are duplicated from react-router. If updating these, please
|
||||
// update the react-router and react-router-native types as well.
|
||||
declare export type Location = {
|
||||
pathname: string,
|
||||
search: string,
|
||||
hash: string,
|
||||
state?: any,
|
||||
key?: string
|
||||
};
|
||||
|
||||
declare export type LocationShape = {
|
||||
pathname?: string,
|
||||
search?: string,
|
||||
hash?: string,
|
||||
state?: any
|
||||
};
|
||||
|
||||
declare export type HistoryAction = "PUSH" | "REPLACE" | "POP";
|
||||
|
||||
declare export type RouterHistory = {
|
||||
length: number,
|
||||
location: Location,
|
||||
action: HistoryAction,
|
||||
listen(
|
||||
callback: (location: Location, action: HistoryAction) => void
|
||||
): () => void,
|
||||
push(path: string | LocationShape, state?: any): void,
|
||||
replace(path: string | LocationShape, state?: any): void,
|
||||
go(n: number): void,
|
||||
goBack(): void,
|
||||
goForward(): void,
|
||||
canGo?: (n: number) => boolean,
|
||||
block(
|
||||
callback: (location: Location, action: HistoryAction) => boolean
|
||||
): void,
|
||||
// createMemoryHistory
|
||||
index?: number,
|
||||
entries?: Array<Location>
|
||||
};
|
||||
|
||||
declare export type Match = {
|
||||
params: { [key: string]: ?string },
|
||||
isExact: boolean,
|
||||
path: string,
|
||||
url: string
|
||||
};
|
||||
|
||||
declare export type ContextRouter = {|
|
||||
history: RouterHistory,
|
||||
location: Location,
|
||||
match: Match,
|
||||
staticContext?: StaticRouterContext,
|
||||
|};
|
||||
|
||||
declare export type GetUserConfirmation = (
|
||||
message: string,
|
||||
callback: (confirmed: boolean) => void
|
||||
) => void;
|
||||
|
||||
declare type StaticRouterContext = {
|
||||
url?: string
|
||||
};
|
||||
|
||||
declare export class StaticRouter extends React$Component<{
|
||||
basename?: string,
|
||||
location?: string | Location,
|
||||
context: StaticRouterContext,
|
||||
children?: React$Node
|
||||
}> {}
|
||||
|
||||
declare export class MemoryRouter extends React$Component<{
|
||||
initialEntries?: Array<LocationShape | string>,
|
||||
initialIndex?: number,
|
||||
getUserConfirmation?: GetUserConfirmation,
|
||||
keyLength?: number,
|
||||
children?: React$Node
|
||||
}> {}
|
||||
|
||||
declare export class Router extends React$Component<{
|
||||
history: RouterHistory,
|
||||
children?: React$Node
|
||||
}> {}
|
||||
|
||||
declare export class Prompt extends React$Component<{
|
||||
message: string | ((location: Location) => string | boolean),
|
||||
when?: boolean
|
||||
}> {}
|
||||
|
||||
declare export class Redirect extends React$Component<{
|
||||
to: string | LocationShape,
|
||||
push?: boolean
|
||||
}> {}
|
||||
|
||||
declare export class Route extends React$Component<{
|
||||
component?: React$ComponentType<*>,
|
||||
render?: (router: ContextRouter) => React$Node,
|
||||
children?: React$ComponentType<ContextRouter> | React$Node,
|
||||
path?: string,
|
||||
exact?: boolean,
|
||||
strict?: boolean
|
||||
}> {}
|
||||
|
||||
declare export class Switch extends React$Component<{
|
||||
children?: React$Node
|
||||
}> {}
|
||||
|
||||
declare export function withRouter<P>(
|
||||
Component: React$ComponentType<{| ...ContextRouter, ...P |}>
|
||||
): React$ComponentType<P>;
|
||||
|
||||
declare type MatchPathOptions = {
|
||||
path?: string,
|
||||
exact?: boolean,
|
||||
sensitive?: boolean,
|
||||
strict?: boolean
|
||||
};
|
||||
|
||||
declare export function matchPath(
|
||||
pathname: string,
|
||||
options?: MatchPathOptions | string
|
||||
): null | Match;
|
||||
}
|
44
src/js/flowtype/react-router-redux.js
vendored
Normal file
44
src/js/flowtype/react-router-redux.js
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
import type {
|
||||
RouterHistory,
|
||||
Location as RouterLocation
|
||||
} from 'react-router';
|
||||
|
||||
declare module "react-router-redux" {
|
||||
|
||||
// custom state for location
|
||||
declare export type LocationState = {[key: string] : string};
|
||||
|
||||
declare export type Location = {
|
||||
pathname: string,
|
||||
search: string,
|
||||
hash: string,
|
||||
key?: string,
|
||||
state: LocationState
|
||||
}
|
||||
|
||||
declare export var LOCATION_CHANGE: "@@router/LOCATION_CHANGE";
|
||||
|
||||
declare export type RouterAction = {
|
||||
type: typeof LOCATION_CHANGE,
|
||||
// type: "@@router/LOCATION_CHANGE",
|
||||
payload: Location;
|
||||
}
|
||||
|
||||
declare export type State = {
|
||||
location: Location; // should be ?Location
|
||||
}
|
||||
|
||||
declare export function push(a: string): void;
|
||||
declare export function replace(a: string): void;
|
||||
declare export function go(a: string): void;
|
||||
declare export function goBack(): void;
|
||||
declare export function goForward(): void;
|
||||
|
||||
//declare export function routerReducer<S, A>(state?: S, action: A): S;
|
||||
declare export function routerReducer(state?: State, action: any): State;
|
||||
declare export function routerMiddleware(history: any): any;
|
||||
|
||||
declare export class ConnectedRouter extends React$Component<{
|
||||
history: any
|
||||
}> {}
|
||||
}
|
123
src/js/flowtype/react-router_v4.x.x.js
Normal file
123
src/js/flowtype/react-router_v4.x.x.js
Normal file
@ -0,0 +1,123 @@
|
||||
declare module "react-router" {
|
||||
// NOTE: many of these are re-exported by react-router-dom and
|
||||
// react-router-native, so when making changes, please be sure to update those
|
||||
// as well.
|
||||
declare export type Location = {
|
||||
pathname: string,
|
||||
search: string,
|
||||
hash: string,
|
||||
state?: any,
|
||||
key?: string
|
||||
};
|
||||
|
||||
declare export type LocationShape = {
|
||||
pathname?: string,
|
||||
search?: string,
|
||||
hash?: string,
|
||||
state?: any
|
||||
};
|
||||
|
||||
declare export type HistoryAction = "PUSH" | "REPLACE" | "POP";
|
||||
|
||||
declare export type RouterHistory = {
|
||||
length: number,
|
||||
location: Location,
|
||||
action: HistoryAction,
|
||||
listen(
|
||||
callback: (location: Location, action: HistoryAction) => void
|
||||
): () => void,
|
||||
push(path: string | LocationShape, state?: any): void,
|
||||
replace(path: string | LocationShape, state?: any): void,
|
||||
go(n: number): void,
|
||||
goBack(): void,
|
||||
goForward(): void,
|
||||
canGo?: (n: number) => boolean,
|
||||
block(
|
||||
callback: (location: Location, action: HistoryAction) => boolean
|
||||
): void,
|
||||
// createMemoryHistory
|
||||
index?: number,
|
||||
entries?: Array<Location>
|
||||
};
|
||||
|
||||
declare export type Match = {
|
||||
params: { [key: string]: ?string },
|
||||
isExact: boolean,
|
||||
path: string,
|
||||
url: string
|
||||
};
|
||||
|
||||
declare export type ContextRouter = {|
|
||||
history: RouterHistory,
|
||||
location: Location,
|
||||
match: Match,
|
||||
staticContext?: StaticRouterContext
|
||||
|};
|
||||
|
||||
declare export type GetUserConfirmation = (
|
||||
message: string,
|
||||
callback: (confirmed: boolean) => void
|
||||
) => void;
|
||||
|
||||
declare type StaticRouterContext = {
|
||||
url?: string
|
||||
};
|
||||
|
||||
declare export class StaticRouter extends React$Component<{
|
||||
basename?: string,
|
||||
location?: string | Location,
|
||||
context: StaticRouterContext,
|
||||
children?: React$Node
|
||||
}> {}
|
||||
|
||||
declare export class MemoryRouter extends React$Component<{
|
||||
initialEntries?: Array<LocationShape | string>,
|
||||
initialIndex?: number,
|
||||
getUserConfirmation?: GetUserConfirmation,
|
||||
keyLength?: number,
|
||||
children?: React$Node
|
||||
}> {}
|
||||
|
||||
declare export class Router extends React$Component<{
|
||||
history: RouterHistory,
|
||||
children?: React$Node
|
||||
}> {}
|
||||
|
||||
declare export class Prompt extends React$Component<{
|
||||
message: string | ((location: Location) => string | true),
|
||||
when?: boolean
|
||||
}> {}
|
||||
|
||||
declare export class Redirect extends React$Component<{
|
||||
to: string | LocationShape,
|
||||
push?: boolean
|
||||
}> {}
|
||||
|
||||
declare export class Route extends React$Component<{
|
||||
component?: React$ComponentType<*>,
|
||||
render?: (router: ContextRouter) => React$Node,
|
||||
children?: React$ComponentType<ContextRouter> | React$Node,
|
||||
path?: string,
|
||||
exact?: boolean,
|
||||
strict?: boolean
|
||||
}> {}
|
||||
|
||||
declare export class Switch extends React$Component<{
|
||||
children?: React$Node
|
||||
}> {}
|
||||
|
||||
declare export function withRouter<P>(
|
||||
Component: React$ComponentType<{| ...ContextRouter, ...P |}>
|
||||
): React$ComponentType<P>;
|
||||
|
||||
declare type MatchPathOptions = {
|
||||
path?: string,
|
||||
exact?: boolean,
|
||||
strict?: boolean,
|
||||
sensitive?: boolean
|
||||
};
|
||||
declare export function matchPath(
|
||||
pathname: string,
|
||||
options?: MatchPathOptions | string
|
||||
): null | Match;
|
||||
}
|
72
src/js/flowtype/redux_v3.x.x.js
Normal file
72
src/js/flowtype/redux_v3.x.x.js
Normal file
@ -0,0 +1,72 @@
|
||||
// flow-typed signature: cca4916b0213065533df8335c3285a4a
|
||||
// flow-typed version: cab04034e7/redux_v3.x.x/flow_>=v0.55.x
|
||||
|
||||
declare module 'redux' {
|
||||
|
||||
/*
|
||||
|
||||
S = State
|
||||
A = Action
|
||||
D = Dispatch
|
||||
|
||||
*/
|
||||
|
||||
declare export type DispatchAPI<A> = (action: A) => A;
|
||||
// declare export type Dispatch<A: { type: $Subtype<string> }> = DispatchAPI<A>;
|
||||
|
||||
declare export type ThunkAction<S, A> = (dispatch: Dispatch<S, A>, getState: () => S) => Promise<void> | void;
|
||||
declare export type ThunkDispatch<S, A> = (action: ThunkAction<S, A>) => void;
|
||||
|
||||
declare export type PlainDispatch<A: {type: $Subtype<string>}> = DispatchAPI<A>;
|
||||
/* NEW: Dispatch is now a combination of these different dispatch types */
|
||||
declare export type Dispatch<S, A> = PlainDispatch<A> & ThunkDispatch<S, A>;
|
||||
|
||||
// declare export type ThunkAction<S, D> = (dispatch: D, getState: () => S) => Promise<void> | void;
|
||||
// declare type ThunkDispatch<S, D> = (action: ThunkAction<S, D & ThunkDispatch<S, D>>) => void;
|
||||
|
||||
declare export type MiddlewareAPI<S, A> = {
|
||||
dispatch: Dispatch<S, A>;
|
||||
getState(): S;
|
||||
};
|
||||
|
||||
declare export type Store<S, A, D = Dispatch<S, A>> = {
|
||||
// rewrite MiddlewareAPI members in order to get nicer error messages (intersections produce long messages)
|
||||
dispatch: D;
|
||||
getState(): S;
|
||||
subscribe(listener: () => void): () => void;
|
||||
replaceReducer(nextReducer: Reducer<S, A>): void
|
||||
};
|
||||
|
||||
declare export type Reducer<S, A> = (state: S | void, action: A) => S;
|
||||
|
||||
declare export type CombinedReducer<S, A> = (state: $Shape<S> & {} | void, action: A) => S;
|
||||
|
||||
declare export type Middleware<S, A> =
|
||||
(api: MiddlewareAPI<S, A>) =>
|
||||
(next: PlainDispatch<A>) => PlainDispatch<A>;
|
||||
|
||||
declare export type StoreCreator<S, A, D = Dispatch<S, A>> = {
|
||||
(reducer: Reducer<S, A>, enhancer?: StoreEnhancer<S, A, D>): Store<S, A, D>;
|
||||
(reducer: Reducer<S, A>, preloadedState: S, enhancer?: StoreEnhancer<S, A, D>): Store<S, A, D>;
|
||||
};
|
||||
|
||||
declare export type StoreEnhancer<S, A, D = Dispatch<S, A>> = (next: StoreCreator<S, A, D>) => StoreCreator<S, A, D>;
|
||||
|
||||
declare export function createStore<S, A, D>(reducer: Reducer<S, A>, enhancer?: StoreEnhancer<S, A, D>): Store<S, A, D>;
|
||||
declare export function createStore<S, A, D>(reducer: Reducer<S, A>, preloadedState?: S, enhancer?: StoreEnhancer<S, A, D>): Store<S, A, D>;
|
||||
|
||||
declare export function applyMiddleware<S, A, D>(...middlewares: Array<Middleware<S, A>>): StoreEnhancer<S, A, D>;
|
||||
|
||||
declare export type ActionCreator<A, B> = (...args: Array<B>) => A;
|
||||
declare export type ActionCreators<K, A> = { [key: K]: ActionCreator<A, any> };
|
||||
|
||||
declare export function bindActionCreators<A, C: ActionCreator<A, any>, D: DispatchAPI<A>>(actionCreator: C, dispatch: D): C;
|
||||
declare export function bindActionCreators<A, K, C: ActionCreators<K, A>, D: DispatchAPI<A>>(actionCreators: C, dispatch: D): C;
|
||||
// declare export function bindActionCreators<A, C: ActionCreator<A, any>, D: Dispatch>(actionCreator: C, dispatch: D): C;
|
||||
// declare export function bindActionCreators<A, K, C: ActionCreators<K, A>, D: Dispatch>(actionCreators: C, dispatch: D): C;
|
||||
|
||||
declare export function combineReducers<O: Object, A>(reducers: O): CombinedReducer<$ObjMap<O, <S>(r: Reducer<S, any>) => S>, A>;
|
||||
|
||||
declare export var compose: $Compose;
|
||||
}
|
||||
|
195
src/js/flowtype/trezor-connect.js
Normal file
195
src/js/flowtype/trezor-connect.js
Normal file
@ -0,0 +1,195 @@
|
||||
declare module 'trezor-connect' {
|
||||
|
||||
// CONSTANTS (from trezor-connect/src/js/constants)
|
||||
|
||||
declare type T_DEVICE_EVENT = 'DEVICE_EVENT';
|
||||
declare type T_DEVICE = {
|
||||
CONNECT: 'device__connect',
|
||||
CONNECT_UNACQUIRED: 'device__connect_unacquired',
|
||||
DISCONNECT: 'device__disconnect',
|
||||
DISCONNECT_UNACQUIRED: 'device__disconnect_unacquired',
|
||||
|
||||
ACQUIRE: 'device__acquire', // remove? internal
|
||||
RELEASE: 'device__release', // internal
|
||||
ACQUIRED: 'device__acquired',
|
||||
RELEASED: 'device__released', // internal
|
||||
USED_ELSEWHERE: 'device__used_elsewhere', // internal
|
||||
CHANGED: 'device__changed',
|
||||
|
||||
LOADING: 'device__loading', // internal
|
||||
|
||||
// trezor-link events
|
||||
BUTTON: 'button',
|
||||
PIN: 'pin',
|
||||
PASSPHRASE: 'passphrase',
|
||||
PASSPHRASE_ON_DEVICE: 'passphrase_on_device',
|
||||
WORD: 'word',
|
||||
|
||||
// custom (not emitted)
|
||||
// AUTHENTICATED: 'device__authenticated',
|
||||
// WAIT_FOR_SELECTION: 'device__wait_for_selection',
|
||||
};
|
||||
|
||||
declare type T_UI_EVENT = 'UI_EVENT';
|
||||
declare type T_UI = {
|
||||
TRANSPORT: 'ui-no_transport',
|
||||
BOOTLOADER: 'ui-device_bootloader_mode',
|
||||
INITIALIZE: 'ui-device_not_initialized',
|
||||
FIRMWARE: 'ui-device_firmware_old',
|
||||
BROWSER_NOT_SUPPORTED: 'ui-browser_not_supported',
|
||||
BROWSER_OUTDATED: 'ui-browser_outdated',
|
||||
RECEIVE_BROWSER: 'ui-receive_browser',
|
||||
REQUEST_UI_WINDOW: 'ui-request_window',
|
||||
CLOSE_UI_WINDOW: 'ui-close_window',
|
||||
REQUEST_PERMISSION: 'ui-request_permission',
|
||||
REQUEST_CONFIRMATION: 'ui-request_confirmation',
|
||||
REQUEST_PIN: 'ui-request_pin',
|
||||
INVALID_PIN: 'ui-invalid_pin',
|
||||
REQUEST_PASSPHRASE: 'ui-request_passphrase',
|
||||
REQUEST_PASSPHRASE_ON_DEVICE: 'ui-request_passphrase_on_device',
|
||||
CONNECT: 'ui-connect',
|
||||
LOADING: 'ui-loading',
|
||||
SET_OPERATION: 'ui-set_operation',
|
||||
SELECT_DEVICE: 'ui-select_device',
|
||||
SELECT_ACCOUNT: 'ui-select_account',
|
||||
SELECT_FEE: 'ui-select_fee',
|
||||
UPDATE_CUSTOM_FEE: 'ui-update_custom_fee',
|
||||
INSUFFICIENT_FUNDS: 'ui-insufficient_funds',
|
||||
REQUEST_BUTTON: 'ui-button',
|
||||
RECEIVE_PERMISSION: 'ui-receive_permission',
|
||||
RECEIVE_CONFIRMATION: 'ui-receive_confirmation',
|
||||
RECEIVE_PIN: 'ui-receive_pin',
|
||||
RECEIVE_PASSPHRASE: 'ui-receive_passphrase',
|
||||
RECEIVE_DEVICE: 'ui-receive_device',
|
||||
CHANGE_ACCOUNT: 'ui-change_account',
|
||||
RECEIVE_ACCOUNT: 'ui-receive_account',
|
||||
RECEIVE_FEE: 'ui-receive_fee',
|
||||
CHANGE_SETTINGS: 'ui-change_settings',
|
||||
};
|
||||
|
||||
declare type T_TRANSPORT_EVENT = 'TRANSPORT_EVENT';
|
||||
declare type T_TRANSPORT = {
|
||||
START: 'transport__start',
|
||||
ERROR: 'transport__error',
|
||||
UPDATE: 'transport__update',
|
||||
STREAM: 'transport__stream',
|
||||
REQUEST: 'transport__request_device',
|
||||
UNREADABLE: 'transport__unreadable_hid_device',
|
||||
RECONNECT: 'transport__reconnect'
|
||||
};
|
||||
|
||||
|
||||
|
||||
declare export type ResponseMessage = {
|
||||
event: string;
|
||||
type: string;
|
||||
id: number;
|
||||
success: boolean;
|
||||
payload: Object;
|
||||
}
|
||||
|
||||
declare export type UiMessageType = $Values<T_UI>;
|
||||
declare export type UiMessage = {
|
||||
event: string;
|
||||
type: UiMessageType;
|
||||
payload: Object;
|
||||
}
|
||||
|
||||
declare export type DeviceMessageType = $Values<T_DEVICE>;
|
||||
declare export type DeviceMessage = {
|
||||
event: string;
|
||||
type: DeviceMessageType;
|
||||
payload: Device;
|
||||
}
|
||||
|
||||
declare export type TransportMessageType = $Values<T_TRANSPORT>;
|
||||
declare export type TransportMessage = {
|
||||
event: string;
|
||||
type: TransportMessageType;
|
||||
payload: Object;
|
||||
}
|
||||
|
||||
declare export type Device = {
|
||||
path: string,
|
||||
label: string,
|
||||
isUsedElsewhere: boolean,
|
||||
featuresNeedsReload: boolean,
|
||||
unacquired?: boolean,
|
||||
features: Features,
|
||||
}
|
||||
|
||||
declare export type Features = {
|
||||
vendor: string,
|
||||
major_version: number,
|
||||
minor_version: number,
|
||||
patch_version: number,
|
||||
bootloader_mode: boolean,
|
||||
device_id: string,
|
||||
pin_protection: boolean,
|
||||
passphrase_protection: boolean,
|
||||
language: string,
|
||||
label: string,
|
||||
// coins: CoinType[],
|
||||
coins: Array<any>,
|
||||
initialized: boolean,
|
||||
revision: string,
|
||||
bootloader_hash: string,
|
||||
imported: boolean,
|
||||
pin_cached: boolean,
|
||||
passphrase_cached: boolean,
|
||||
state?: string;
|
||||
needs_backup?: boolean,
|
||||
firmware_present?: boolean,
|
||||
}
|
||||
|
||||
// declare export interface TrezorConnect = {
|
||||
// on: (type: string, handler: (event: any) => void) => void;
|
||||
// }
|
||||
|
||||
declare type OnEvents = "device__event";
|
||||
|
||||
// declare type TRANSPORT = {
|
||||
// ERROR: 'transport__error';
|
||||
// READY: 'transport__ready';
|
||||
// }
|
||||
|
||||
declare type DeviceEventListener = (type: T_DEVICE_EVENT, handler: (event: DeviceMessage) => void) => void;
|
||||
declare type DeviceEventListenerByType = (type: DeviceMessageType, handler: (device: Device) => void) => void;
|
||||
declare type UiEventListener = (type: T_UI_EVENT, handler: (event: UiMessage) => void) => void;
|
||||
declare type TransportEventListener = (type: T_TRANSPORT_EVENT, handler: (event: TransportMessage) => void) => void;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
declare module.exports: {
|
||||
init: (options: Object) => Promise<Object>;
|
||||
// on: (type: string, handler: (event: any) => void) => void;
|
||||
on: DeviceEventListener & DeviceEventListenerByType & UiEventListener & TransportEventListener;
|
||||
off: (type: string, handler: (event: any) => void) => void;
|
||||
getVersion: () => any;
|
||||
renderWebUSBButton: (className?: string) => void;
|
||||
|
||||
getDeviceState: (options: Object) => Promise<Object>;
|
||||
getFeatures: (options: Object) => Promise<Object>;
|
||||
getPublicKey: (options: Object) => Promise<Object>;
|
||||
ethereumGetAddress: (options: Object) => Promise<Object>;
|
||||
uiResponse: (options: Object) => Promise<Object>;
|
||||
|
||||
ethereumSignTransaction: (options: Object) => Promise<Object>;
|
||||
|
||||
|
||||
// export const RESPONSE_EVENT: string = 'RESPONSE_EVENT';
|
||||
// export const ERROR_EVENT: string = 'ERROR_EVENT';
|
||||
|
||||
DEVICE_EVENT: T_DEVICE_EVENT;
|
||||
DEVICE: T_DEVICE;
|
||||
|
||||
|
||||
UI_EVENT: T_UI_EVENT;
|
||||
UI: T_UI;
|
||||
|
||||
TRANSPORT_EVENT: T_TRANSPORT_EVENT;
|
||||
TRANSPORT: T_TRANSPORT;
|
||||
};
|
||||
}
|
75
src/js/flowtype/web3.js
Normal file
75
src/js/flowtype/web3.js
Normal file
@ -0,0 +1,75 @@
|
||||
declare module 'web3' {
|
||||
|
||||
module.exports = {
|
||||
eth: {
|
||||
_requestManager: any;
|
||||
iban: {
|
||||
(iban: string): void;
|
||||
fromAddress: (address: string) => any;
|
||||
fromBban: (bban: string) => any;
|
||||
createIndirect: (options: any) => any;
|
||||
isValid: (iban: string) => boolean;
|
||||
};
|
||||
sendIBANTransaction: any;
|
||||
contract: (abi: any) => {
|
||||
eth: any;
|
||||
abi: any[];
|
||||
new: (...args: any[]) => {
|
||||
_eth: any;
|
||||
transactionHash: any;
|
||||
address: any;
|
||||
abi: any[];
|
||||
};
|
||||
at: (address: any, callback: Function) => any;
|
||||
getData: (...args: any[]) => any;
|
||||
};
|
||||
filter: (fil: any, callback: any, filterCreationErrorCallback: any) => {
|
||||
requestManager: any;
|
||||
options: any;
|
||||
implementation: {
|
||||
[x: string]: any;
|
||||
};
|
||||
filterId: any;
|
||||
callbacks: any[];
|
||||
getLogsCallbacks: any[];
|
||||
pollFilters: any[];
|
||||
formatter: any;
|
||||
watch: (callback: any) => any;
|
||||
stopWatching: (callback: any) => any;
|
||||
get: (callback: any) => any;
|
||||
};
|
||||
namereg: () => {
|
||||
eth: any;
|
||||
abi: any[];
|
||||
new: (...args: any[]) => {
|
||||
_eth: any;
|
||||
transactionHash: any;
|
||||
address: any;
|
||||
abi: any[];
|
||||
};
|
||||
at: (address: any, callback: Function) => any;
|
||||
getData: (...args: any[]) => any;
|
||||
};
|
||||
icapNamereg: () => {
|
||||
eth: any;
|
||||
abi: any[];
|
||||
new: (...args: any[]) => {
|
||||
_eth: any;
|
||||
transactionHash: any;
|
||||
address: any;
|
||||
abi: any[];
|
||||
};
|
||||
at: (address: any, callback: Function) => any;
|
||||
getData: (...args: any[]) => any;
|
||||
};
|
||||
isSyncing: (callback: any) => {
|
||||
requestManager: any;
|
||||
pollId: string;
|
||||
callbacks: any[];
|
||||
lastSyncState: boolean;
|
||||
addCallback: (callback: any) => any;
|
||||
stopWatching: () => void;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -11,13 +11,12 @@ import Raven from 'raven-js';
|
||||
|
||||
import styles from '../styles/index.less';
|
||||
|
||||
|
||||
Raven.config('https://497392c3ff6e46dc9e54eef123979378@sentry.io/294339').install();
|
||||
|
||||
render(
|
||||
router,
|
||||
document.getElementById('root')
|
||||
);
|
||||
const root: ?HTMLElement = document.getElementById('root');
|
||||
if (root) {
|
||||
render(router, root);
|
||||
}
|
||||
|
||||
window.onbeforeunload = () => {
|
||||
store.dispatch( onBeforeUnload() );
|
||||
|
@ -4,26 +4,43 @@
|
||||
import * as ACCOUNT from '../actions/constants/account';
|
||||
import * as CONNECT from '../actions/constants/TrezorConnect';
|
||||
|
||||
import type { Action } from '../flowtype';
|
||||
import type { Coin } from './LocalStorageReducer';
|
||||
|
||||
export type State = {
|
||||
+index: number;
|
||||
+deviceState: ?string;
|
||||
+deviceId: ?string;
|
||||
+deviceInstance: ?string;
|
||||
+deviceState: string;
|
||||
+deviceId: string;
|
||||
+deviceInstance: ?number;
|
||||
+network: string;
|
||||
+coin: Coin;
|
||||
location: string;
|
||||
}
|
||||
|
||||
export const initialState: State = {
|
||||
index: 0,
|
||||
deviceState: null,
|
||||
deviceId: null,
|
||||
deviceState: '0',
|
||||
deviceId: '0',
|
||||
deviceInstance: null,
|
||||
network: '',
|
||||
coin: {
|
||||
name: '',
|
||||
network: '',
|
||||
symbol: '',
|
||||
bip44: '',
|
||||
defaultGasLimit: 0,
|
||||
defaultGasLimitTokens: 0,
|
||||
defaultGasPrice: 0,
|
||||
explorer: '',
|
||||
tokens: '',
|
||||
backends: []
|
||||
},
|
||||
location: '',
|
||||
|
||||
};
|
||||
|
||||
|
||||
export default (state: State = initialState, action: any): State => {
|
||||
export default (state: State = initialState, action: Action): State => {
|
||||
|
||||
switch (action.type) {
|
||||
|
||||
@ -33,7 +50,6 @@ export default (state: State = initialState, action: any): State => {
|
||||
case ACCOUNT.DISPOSE :
|
||||
return initialState;
|
||||
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ const createAccount = (state: Array<Account>, action: any): Array<Account> => {
|
||||
// TODO check with device_id
|
||||
// check if account was created before
|
||||
const exist: ?Account = state.find((account: Account) => account.address === action.address && account.network === action.network && account.deviceID === action.device.features.device_id);
|
||||
console.warn("MAM?", exist, action)
|
||||
if (exist) {
|
||||
return state;
|
||||
}
|
||||
|
@ -7,8 +7,10 @@ import * as CONNECT from '../actions/constants/TrezorConnect';
|
||||
|
||||
export type Discovery = {
|
||||
network: string;
|
||||
deviceState: string;
|
||||
xpub: string;
|
||||
hdKey: any;
|
||||
basePath: any;
|
||||
deviceState: string;
|
||||
accountIndex: number;
|
||||
interrupted: boolean;
|
||||
completed: boolean;
|
||||
@ -81,6 +83,8 @@ const waiting = (state: Array<Discovery>, action: any): Array<Discovery> => {
|
||||
network: action.network,
|
||||
deviceState: action.device.state,
|
||||
xpub: '',
|
||||
hdKey: null,
|
||||
basePath: null,
|
||||
accountIndex: 0,
|
||||
interrupted: false,
|
||||
completed: false,
|
||||
@ -98,7 +102,7 @@ const waiting = (state: Array<Discovery>, action: any): Array<Discovery> => {
|
||||
return newState;
|
||||
}
|
||||
|
||||
export default function discovery(state: Array<Discovery> = initialState, action: any): any {
|
||||
export default function discovery(state: Array<Discovery> = initialState, action: any): Array<Discovery> {
|
||||
|
||||
switch (action.type) {
|
||||
case DISCOVERY.START :
|
||||
|
@ -1,6 +1,11 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
import { RATE_UPDATE } from '../services/CoinmarketcapService';
|
||||
|
||||
import type { Action } from '../flowtype';
|
||||
import type { FiatRateAction } from '../services/CoinmarketcapService';
|
||||
|
||||
export type Fiat = {
|
||||
+network: string;
|
||||
value: string;
|
||||
@ -8,7 +13,7 @@ export type Fiat = {
|
||||
|
||||
export const initialState: Array<Fiat> = [];
|
||||
|
||||
const update = (state: Array<Fiat>, action: any): Array<Fiat> => {
|
||||
const update = (state: Array<Fiat>, action: FiatRateAction): Array<Fiat> => {
|
||||
const newState: Array<Fiat> = [ ...state ];
|
||||
const exists: ?Fiat = newState.find(f => f.network === action.network);
|
||||
if (exists) {
|
||||
@ -23,11 +28,11 @@ const update = (state: Array<Fiat>, action: any): Array<Fiat> => {
|
||||
}
|
||||
|
||||
|
||||
export default (state: Array<Fiat> = initialState, action: any): Array<Fiat> => {
|
||||
export default (state: Array<Fiat> = initialState, action: Action): Array<Fiat> => {
|
||||
|
||||
switch (action.type) {
|
||||
|
||||
case 'rate__update' :
|
||||
case RATE_UPDATE :
|
||||
return update(state, action);
|
||||
|
||||
default:
|
||||
|
@ -3,23 +3,77 @@
|
||||
|
||||
import * as STORAGE from '../actions/constants/localStorage';
|
||||
|
||||
type State = {
|
||||
import type { Action } from '../flowtype';
|
||||
|
||||
export type Coin = {
|
||||
name: string;
|
||||
network: string;
|
||||
symbol: string;
|
||||
bip44: string;
|
||||
defaultGasLimit: number;
|
||||
defaultGasLimitTokens: number;
|
||||
defaultGasPrice: number;
|
||||
explorer: string;
|
||||
tokens: string;
|
||||
backends: Array<any>
|
||||
}
|
||||
|
||||
export type NetworkToken = {
|
||||
address: string,
|
||||
name: string,
|
||||
symbol: string,
|
||||
decimals: number
|
||||
}
|
||||
|
||||
export type TokensCollection = { [network: string]: Array<NetworkToken> };
|
||||
|
||||
// type AbiField = {
|
||||
// constant: boolean,
|
||||
// inputs: Array<{
|
||||
// name: string,
|
||||
// type: string,
|
||||
// }>,
|
||||
// name: string,
|
||||
// outputs: Array<{
|
||||
// name: string,
|
||||
// type: string,
|
||||
// }>,
|
||||
// payable: boolean,
|
||||
// stateMutability: string,
|
||||
// type: string
|
||||
// }
|
||||
|
||||
export type FiatValueTicker = {
|
||||
network: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export type Config = {
|
||||
coins: Array<Coin>;
|
||||
fiatValueTickers: Array<FiatValueTicker>;
|
||||
}
|
||||
|
||||
|
||||
export type State = {
|
||||
initialized: boolean;
|
||||
error: any;
|
||||
config: any;
|
||||
ERC20Abi: any;
|
||||
tokens: any;
|
||||
error: ?string;
|
||||
config: Config;
|
||||
ERC20Abi: Array<Object>;
|
||||
tokens: TokensCollection;
|
||||
}
|
||||
|
||||
const initialState: State = {
|
||||
initialized: false,
|
||||
error: null,
|
||||
config: null,
|
||||
ERC20Abi: null,
|
||||
tokens: null,
|
||||
config: {
|
||||
coins: [],
|
||||
fiatValueTickers: []
|
||||
},
|
||||
ERC20Abi: [],
|
||||
tokens: {},
|
||||
};
|
||||
|
||||
export default function localStorage(state: State = initialState, action: any): any {
|
||||
export default function localStorage(state: State = initialState, action: Action): State {
|
||||
|
||||
switch (action.type) {
|
||||
|
||||
@ -44,4 +98,4 @@ export default function localStorage(state: State = initialState, action: any):
|
||||
return state;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
import * as LOG from '../actions/constants/log';
|
||||
import type { Action } from '../flowtype';
|
||||
|
||||
type LogEntry = {
|
||||
time: number;
|
||||
type: string;
|
||||
@ -18,26 +21,26 @@ export const initialState: State = {
|
||||
};
|
||||
|
||||
|
||||
export default (state: State = initialState, action: any): State => {
|
||||
export default (state: State = initialState, action: Action): State => {
|
||||
|
||||
switch (action.type) {
|
||||
|
||||
case 'log__open':
|
||||
case LOG.OPEN:
|
||||
return {
|
||||
...state,
|
||||
opened: true
|
||||
}
|
||||
|
||||
case 'log__close':
|
||||
case LOG.CLOSE:
|
||||
return {
|
||||
...state,
|
||||
opened: false
|
||||
}
|
||||
|
||||
case 'log__add':
|
||||
return {
|
||||
...state,
|
||||
}
|
||||
// case 'log__add':
|
||||
// return {
|
||||
// ...state,
|
||||
// }
|
||||
|
||||
default:
|
||||
return state;
|
||||
|
@ -6,21 +6,21 @@ import * as RECEIVE from '../actions/constants/receive';
|
||||
import * as MODAL from '../actions/constants/modal';
|
||||
import * as CONNECT from '../actions/constants/TrezorConnect';
|
||||
|
||||
type ModalState = {
|
||||
export type State = {
|
||||
opened: boolean;
|
||||
device: any;
|
||||
instances: Array<any>;
|
||||
instances: ?Array<any>;
|
||||
windowType: ?string;
|
||||
}
|
||||
|
||||
const initialState: ModalState = {
|
||||
const initialState: State = {
|
||||
opened: false,
|
||||
device: null,
|
||||
instances: null,
|
||||
windowType: null
|
||||
};
|
||||
|
||||
export default function modal(state: ModalState = initialState, action: any): any {
|
||||
export default function modal(state: State = initialState, action: any): State {
|
||||
|
||||
switch (action.type) {
|
||||
|
||||
|
@ -7,7 +7,7 @@ import { DEVICE } from 'trezor-connect';
|
||||
|
||||
type NotificationAction = {
|
||||
label: string;
|
||||
callback: any;
|
||||
callback: Function;
|
||||
}
|
||||
|
||||
type NotificationEntry = {
|
||||
|
@ -34,7 +34,7 @@ const fromStorage = (state: Array<PendingTx>, action: any) => {
|
||||
return state.filter(tx => tx.id !== action.tx.id);
|
||||
}
|
||||
|
||||
export default function pending(state: Array<PendingTx> = initialState, action: any): any {
|
||||
export default function pending(state: Array<PendingTx> = initialState, action: any): Array<PendingTx> {
|
||||
|
||||
switch (action.type) {
|
||||
|
||||
|
@ -5,7 +5,7 @@ import * as RECEIVE from '../actions/constants/receive';
|
||||
|
||||
export type State = {
|
||||
addressVerified: boolean;
|
||||
adressUnverified: boolean;
|
||||
addressUnverified: boolean;
|
||||
}
|
||||
|
||||
export const initialState: State = {
|
||||
|
@ -1,7 +1,6 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
import { LOCATION_CHANGE } from 'react-router-redux';
|
||||
import * as SEND from '../actions/constants/send';
|
||||
import * as WEB3 from '../actions/constants/web3';
|
||||
import * as ADDRESS from '../actions/constants/address';
|
||||
@ -9,7 +8,14 @@ import EthereumjsUnits from 'ethereumjs-units';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { getFeeLevels } from '../actions/SendFormActions';
|
||||
|
||||
import type {
|
||||
Web3CreateAction,
|
||||
Web3UpdateBlockAction,
|
||||
Web3UpdateGasPriceAction
|
||||
} from '../actions/Web3Actions';
|
||||
|
||||
export type State = {
|
||||
+network: string;
|
||||
+coinSymbol: string;
|
||||
token: string;
|
||||
balanceNeedUpdate: boolean;
|
||||
@ -22,7 +28,7 @@ export type State = {
|
||||
amount: string;
|
||||
setMax: boolean;
|
||||
feeLevels: Array<FeeLevel>;
|
||||
selectedFeeLevel: ?FeeLevel;
|
||||
selectedFeeLevel: FeeLevel;
|
||||
recommendedGasPrice: string;
|
||||
gasPriceNeedsUpdate: boolean;
|
||||
gasLimit: string;
|
||||
@ -44,6 +50,7 @@ export type FeeLevel = {
|
||||
|
||||
|
||||
export const initialState: State = {
|
||||
network: '',
|
||||
coinSymbol: '',
|
||||
token: '',
|
||||
|
||||
@ -56,7 +63,11 @@ export const initialState: State = {
|
||||
amount: '',
|
||||
setMax: false,
|
||||
feeLevels: [],
|
||||
selectedFeeLevel: null,
|
||||
selectedFeeLevel: {
|
||||
label: 'Normal',
|
||||
gasPrice: '0',
|
||||
value: 'Normal'
|
||||
},
|
||||
recommendedGasPrice: '0',
|
||||
gasPriceNeedsUpdate: false,
|
||||
gasLimit: '0',
|
||||
@ -71,13 +82,13 @@ export const initialState: State = {
|
||||
}
|
||||
|
||||
|
||||
const onGasPriceUpdated = (state: State, action: any): State => {
|
||||
const onGasPriceUpdated = (state: State, action: Web3UpdateGasPriceAction): State => {
|
||||
|
||||
// function getRandomInt(min, max) {
|
||||
// return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
// }
|
||||
// const newPrice = getRandomInt(10, 50).toString();
|
||||
const newPrice = EthereumjsUnits.convert(action.gasPrice, 'wei', 'gwei');
|
||||
const newPrice: string = EthereumjsUnits.convert(action.gasPrice, 'wei', 'gwei');
|
||||
if (action.network === state.network && newPrice !== state.recommendedGasPrice) {
|
||||
const newState: State = { ...state };
|
||||
if (!state.untouched) {
|
||||
@ -85,7 +96,8 @@ const onGasPriceUpdated = (state: State, action: any): State => {
|
||||
newState.recommendedGasPrice = newPrice;
|
||||
} else {
|
||||
const newFeeLevels = getFeeLevels(state.network, newPrice, state.gasLimit);
|
||||
const selectedFeeLevel = newFeeLevels.find(f => f.value === 'Normal');
|
||||
const selectedFeeLevel: ?FeeLevel = newFeeLevels.find(f => f.value === 'Normal');
|
||||
if (!selectedFeeLevel) return state;
|
||||
newState.recommendedGasPrice = newPrice;
|
||||
newState.feeLevels = newFeeLevels;
|
||||
newState.selectedFeeLevel = selectedFeeLevel;
|
||||
|
@ -2,10 +2,12 @@
|
||||
'use strict';
|
||||
|
||||
import * as SUMMARY from '../actions/constants/summary';
|
||||
import type { Action } from '../flowtype';
|
||||
import type { NetworkToken } from './LocalStorageReducer';
|
||||
|
||||
export type State = {
|
||||
details: boolean;
|
||||
selectedToken: any;
|
||||
selectedToken: ?NetworkToken;
|
||||
}
|
||||
|
||||
export const initialState: State = {
|
||||
@ -14,7 +16,7 @@ export const initialState: State = {
|
||||
};
|
||||
|
||||
|
||||
export default (state: State = initialState, action: any): State => {
|
||||
export default (state: State = initialState, action: Action): State => {
|
||||
|
||||
switch (action.type) {
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user