1
0
mirror of https://github.com/trezor/trezor-wallet synced 2025-02-20 03:52:01 +00:00

AbstractAccound refactor

This commit is contained in:
Szymon Lesisz 2018-04-11 15:21:43 +02:00
parent c2fe9d4b95
commit bb22ca54f0
16 changed files with 130 additions and 186 deletions

View File

@ -3,11 +3,9 @@
import * as ACCOUNT from './constants/account'; import * as ACCOUNT from './constants/account';
import { initialState } from '../reducers/AccountDetailReducer'; import { initialState } from '../reducers/AbstractAccountReducer';
import { findSelectedDevice } from '../reducers/TrezorConnectReducer'; import { findSelectedDevice } from '../reducers/TrezorConnectReducer';
import type { State } from '../reducers/AbstractAccountReducer';
import type { State } from '../reducers/AccountDetailReducer';
import type { Discovery } from '../reducers/DiscoveryReducer';
export const init = (): any => { export const init = (): any => {
return (dispatch, getState): void => { return (dispatch, getState): void => {
@ -18,10 +16,11 @@ export const init = (): any => {
const selected = findSelectedDevice( getState().connect ); const selected = findSelectedDevice( getState().connect );
if (!selected) return; if (!selected) return;
const state: State = { const state: State = {
index: parseInt(urlParams.address), index: parseInt(urlParams.address),
deviceState: selected.state, deviceState: selected.state,
deviceId: selected.features.device_id,
deviceInstance: selected.instance,
network: urlParams.network, network: urlParams.network,
location: location.pathname location: location.pathname
}; };
@ -33,33 +32,21 @@ export const init = (): any => {
} }
} }
export const update = (newProps: any): any => { export const update = (): any => {
return (dispatch, getState): void => { return (dispatch, getState): void => {
const { const {
accountDetail, abstractAccount,
connect,
discovery,
accounts,
router router
} = getState(); } = getState();
const isLocationChanged: boolean = router.location.pathname !== abstractAccount.location;
const isLocationChanged: boolean = newProps.location.pathname !== accountDetail.location;
if (isLocationChanged) { if (isLocationChanged) {
dispatch({ dispatch( init() );
type: ACCOUNT.INIT,
state: {
...accountDetail,
location: newProps.location.pathname,
}
});
return; return;
} }
} }
} }
export const dispose = (device: any): any => { export const dispose = (): any => {
return (dispatch, getState): void => { return (dispatch, getState): void => {
dispatch({ dispatch({
type: ACCOUNT.DISPOSE, type: ACCOUNT.DISPOSE,

View File

@ -12,20 +12,9 @@ import { findSelectedDevice } from '../reducers/TrezorConnectReducer';
export const init = (): any => { export const init = (): any => {
return (dispatch, getState): void => { return (dispatch, getState): void => {
const { location } = getState().router;
const urlParams = location.params;
const selected = findSelectedDevice( getState().connect );
if (!selected) return;
const state: State = { const state: State = {
...initialState, ...initialState,
deviceState: selected.state,
deviceId: selected.features.device_id,
deviceInstance: selected.instance,
accountIndex: parseInt(urlParams.address),
network: urlParams.network,
location: location.pathname,
}; };
dispatch({ dispatch({
@ -39,14 +28,13 @@ export const init = (): any => {
export const update = (newProps: any): any => { export const update = (newProps: any): any => {
return (dispatch, getState): void => { return (dispatch, getState): void => {
const { const {
receive, abstractAccount,
router router
} = getState(); } = getState();
const isLocationChanged: boolean = router.location.pathname !== receive.location; const isLocationChanged: boolean = router.location.pathname !== abstractAccount.location;
if (isLocationChanged) { if (isLocationChanged) {
dispatch( init() ); dispatch( init() );
return;
} }
} }
} }

View File

@ -15,7 +15,9 @@ import { push } from 'react-router-redux';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import { initialState } from '../reducers/SendFormReducer'; import { initialState } from '../reducers/SendFormReducer';
import { findAccount } from '../reducers/AccountsReducer';
import type { State, FeeLevel } from '../reducers/SendFormReducer'; import type { State, FeeLevel } from '../reducers/SendFormReducer';
import type { Account } from '../reducers/AccountsReducer';
import { findSelectedDevice } from '../reducers/TrezorConnectReducer'; import { findSelectedDevice } from '../reducers/TrezorConnectReducer';
//const numberRegExp = new RegExp('^([0-9]{0,10}\\.)?[0-9]{1,18}$'); //const numberRegExp = new RegExp('^([0-9]{0,10}\\.)?[0-9]{1,18}$');
@ -33,7 +35,7 @@ const calculateTotal = (amount: string, gasPrice: string, gasLimit: string): str
} }
} }
export const calculateMaxAmount = (balance: string, gasPrice: string, gasLimit: string): string => { const calculateMaxAmount = (balance: string, gasPrice: string, gasLimit: string): string => {
try { try {
const fee = EthereumjsUnits.convert( new BigNumber(gasPrice).times(gasLimit), 'gwei', 'ether'); const fee = EthereumjsUnits.convert( new BigNumber(gasPrice).times(gasLimit), 'gwei', 'ether');
const b = new BigNumber(balance); const b = new BigNumber(balance);
@ -46,6 +48,10 @@ export const calculateMaxAmount = (balance: string, gasPrice: string, gasLimit:
} }
const getMaxAmount = () => {
}
export const getFeeLevels = (symbol: string, gasPrice: BigNumber | string, gasLimit: string): Array<FeeLevel> => { export const getFeeLevels = (symbol: string, gasPrice: BigNumber | string, gasLimit: string): Array<FeeLevel> => {
if (typeof gasPrice === 'string') gasPrice = new BigNumber(gasPrice); if (typeof gasPrice === 'string') gasPrice = new BigNumber(gasPrice);
const quarter: BigNumber = gasPrice.dividedBy(4); const quarter: BigNumber = gasPrice.dividedBy(4);
@ -77,11 +83,12 @@ export const getFeeLevels = (symbol: string, gasPrice: BigNumber | string, gasLi
} }
export const findBalance = (getState: any): string => { export const findBalance = (getState: any): string => {
const state = getState().sendForm; const accountState = getState().abstractAccount;
const account = getState().accounts.find(a => a.deviceState === state.deviceState && a.index === state.accountIndex && a.network === state.network); const { token } = getState().sendForm;
const account: ?Account = findAccount(getState().accounts, accountState.index, accountState.deviceState, accountState.network);
if (state.token !== state.network) { if (token !== state.network) {
return getState().tokens.find(t => t.ethAddress === account.address && t.symbol === state.token).balance; return getState().tokens.find(t => t.ethAddress === account.address && t.symbol === token).balance;
} else { } else {
return account.balance; return account.balance;
} }
@ -116,14 +123,8 @@ export const init = (): any => {
const state: State = { const state: State = {
...initialState, ...initialState,
deviceState: selected.state,
deviceId: selected.features.device_id,
deviceInstance: selected.instance,
accountIndex: parseInt(urlParams.address),
network: urlParams.network,
coinSymbol: coin.symbol, coinSymbol: coin.symbol,
token: urlParams.network, token: coin.network,
location: location.pathname,
feeLevels, feeLevels,
selectedFeeLevel: feeLevels.find(f => f.value === 'Normal'), selectedFeeLevel: feeLevels.find(f => f.value === 'Normal'),
@ -143,11 +144,11 @@ export const init = (): any => {
export const update = (): any => { export const update = (): any => {
return (dispatch, getState): void => { return (dispatch, getState): void => {
const { const {
sendForm, abstractAccount,
router router
} = getState(); } = getState();
const isLocationChanged: boolean = router.location.pathname !== sendForm.location; const isLocationChanged: boolean = router.location.pathname !== abstractAccount.location;
if (isLocationChanged) { if (isLocationChanged) {
dispatch( init() ); dispatch( init() );
return; return;
@ -170,6 +171,7 @@ export const toggleAdvanced = (address: string): any => {
export const validation = (): any => { export const validation = (): any => {
return (dispatch, getState): void => { return (dispatch, getState): void => {
const accountState = getState().abstractAccount;
const state: State = getState().sendForm; const state: State = getState().sendForm;
const errors: {[k: string]: string} = {}; const errors: {[k: string]: string} = {};
const warnings: {[k: string]: string} = {}; const warnings: {[k: string]: string} = {};
@ -188,7 +190,7 @@ export const validation = (): any => {
} else if (!EthereumjsUtil.isValidAddress(state.address)) { } else if (!EthereumjsUtil.isValidAddress(state.address)) {
errors.address = 'Address is not valid'; errors.address = 'Address is not valid';
} else if (myAccount) { } else if (myAccount) {
if (myAccount.network === state.network) { if (myAccount.network === accountState.network) {
infos.address = `TREZOR Address #${ (myAccount.index + 1) }`; infos.address = `TREZOR Address #${ (myAccount.index + 1) }`;
} else { } else {
// TODO: load coins from config // TODO: load coins from config
@ -206,10 +208,10 @@ export const validation = (): any => {
} else if (state.amount.length > 0 && !state.amount.match(numberRegExp)) { } else if (state.amount.length > 0 && !state.amount.match(numberRegExp)) {
errors.amount = 'Amount is not a number'; errors.amount = 'Amount is not a number';
} else { } else {
const account = getState().accounts.find(a => a.deviceState === state.deviceState && a.index === state.accountIndex && a.network === state.network); const account: ?Account = findAccount(getState().accounts, accountState.index, accountState.deviceState, accountState.network);
let decimalRegExp; let decimalRegExp;
if (state.token !== state.network) { if (state.token !== accountState.network) {
const token: any = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === state.token); const token: any = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === state.token);
if (parseInt(token.decimals) > 0) { if (parseInt(token.decimals) > 0) {
@ -272,7 +274,7 @@ export const validation = (): any => {
} }
// valid data // valid data
if (state.touched.data && state.network === state.token && state.data.length > 0) { if (state.touched.data && accountState.network === state.token && state.data.length > 0) {
const re = /^[0-9A-Fa-f]+$/g; const re = /^[0-9A-Fa-f]+$/g;
//const re = /^[0-9A-Fa-f]{6}$/g; //const re = /^[0-9A-Fa-f]{6}$/g;
if (!re.test(state.data)) { if (!re.test(state.data)) {
@ -319,10 +321,12 @@ export const onAddressChange = (address: string): any => {
export const onAmountChange = (amount: string): any => { export const onAmountChange = (amount: string): any => {
return (dispatch, getState): void => { return (dispatch, getState): void => {
const accountState = getState().abstractAccount;
const currentState: State = getState().sendForm; const currentState: State = getState().sendForm;
const isToken: boolean = currentState.token !== accountState.network;
const touched = { ...currentState.touched }; const touched = { ...currentState.touched };
touched.amount = true; touched.amount = true;
const total: string = calculateTotal(currentState.token !== currentState.network ? '0' : amount, currentState.gasPrice, currentState.gasLimit); const total: string = calculateTotal(isToken ? '0' : amount, currentState.gasPrice, currentState.gasLimit);
const state: State = { const state: State = {
...currentState, ...currentState,
@ -344,23 +348,24 @@ export const onAmountChange = (amount: string): any => {
export const onCurrencyChange = (currency: any): any => { export const onCurrencyChange = (currency: any): any => {
return (dispatch, getState): void => { return (dispatch, getState): void => {
const accountState = getState().abstractAccount;
const currentState = getState().sendForm; const currentState = getState().sendForm;
const isToken: boolean = currency.value !== accountState.network;
const account = getState().accounts.find(a => a.deviceState === currentState.deviceState && a.index === currentState.accountIndex && a.network === currentState.network); const account: ?Account = findAccount(getState().accounts, accountState.index, accountState.deviceState, accountState.network);
if (!account) { if (!account) {
// account not found // account not found
return; return;
} }
const { config } = getState().localStorage; const { config } = getState().localStorage;
const coin = config.coins.find(c => c.network === currentState.network); const coin = config.coins.find(c => c.network === accountState.network);
let gasLimit: string = ''; let gasLimit: string = '';
let amount: string = currentState.amount; let amount: string = currentState.amount;
let total: string; let total: string;
if (currentState.network !== currency.value) { if (isToken) {
gasLimit = coin.defaultGasLimitTokens.toString(); gasLimit = coin.defaultGasLimitTokens.toString();
if (currentState.setMax) { if (currentState.setMax) {
const tokenBalance: string = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === currency.value).balance; const tokenBalance: string = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === currency.value).balance;
@ -399,11 +404,13 @@ export const onCurrencyChange = (currency: any): any => {
export const onSetMax = (): any => { export const onSetMax = (): any => {
return (dispatch, getState): void => { return (dispatch, getState): void => {
const accountState = getState().abstractAccount;
const currentState = getState().sendForm; const currentState = getState().sendForm;
const isToken: boolean = currentState.token !== accountState.network;
const touched = { ...currentState.touched }; const touched = { ...currentState.touched };
touched.amount = true; touched.amount = true;
const account = getState().accounts.find(a => a.deviceState === currentState.deviceState && a.index === currentState.accountIndex && a.network === currentState.network); const account: ?Account = findAccount(getState().accounts, accountState.index, accountState.deviceState, accountState.network);
if (!account) { if (!account) {
// account not found // account not found
return; return;
@ -412,7 +419,7 @@ export const onSetMax = (): any => {
let amount: string = currentState.amount; let amount: string = currentState.amount;
let total: string = currentState.total; let total: string = currentState.total;
if (!currentState.setMax) { if (!currentState.setMax) {
if (currentState.token !== currentState.network) { if (isToken) {
const tokenBalance: string = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === currentState.token).balance; const tokenBalance: string = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === currentState.token).balance;
amount = tokenBalance; amount = tokenBalance;
total = calculateTotal('0', currentState.gasPrice, currentState.gasLimit); total = calculateTotal('0', currentState.gasPrice, currentState.gasLimit);
@ -441,8 +448,10 @@ export const onSetMax = (): any => {
export const onFeeLevelChange = (feeLevel: any): any => { export const onFeeLevelChange = (feeLevel: any): any => {
return (dispatch, getState): void => { return (dispatch, getState): void => {
const accountState = getState().abstractAccount;
const currentState = getState().sendForm; const currentState = getState().sendForm;
const isToken: boolean = currentState.token !== accountState.network;
const state: State = { const state: State = {
...currentState, ...currentState,
untouched: false, untouched: false,
@ -461,15 +470,15 @@ export const onFeeLevelChange = (feeLevel: any): any => {
} }
if (currentState.setMax) { if (currentState.setMax) {
const account = getState().accounts.find(a => a.deviceState === currentState.deviceState && a.index === currentState.accountIndex && a.network === currentState.network); const account: ?Account = findAccount(getState().accounts, accountState.index, accountState.deviceState, accountState.network);
if (state.token !== state.network) { if (isToken) {
const tokenBalance: string = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === currentState.token).balance; const tokenBalance: string = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === currentState.token).balance;
state.amount = tokenBalance; state.amount = tokenBalance;
} else { } else {
state.amount = calculateMaxAmount(account.balance, state.gasPrice, state.gasLimit); state.amount = calculateMaxAmount(account.balance, state.gasPrice, state.gasLimit);
} }
} }
state.total = calculateTotal(state.token !== state.network ? '0' : state.amount, state.gasPrice, state.gasLimit); state.total = calculateTotal(isToken ? '0' : state.amount, state.gasPrice, state.gasLimit);
dispatch({ dispatch({
type: SEND.FEE_LEVEL_CHANGE, type: SEND.FEE_LEVEL_CHANGE,
@ -481,7 +490,10 @@ export const onFeeLevelChange = (feeLevel: any): any => {
export const updateFeeLevels = (): any => { export const updateFeeLevels = (): any => {
return (dispatch, getState): void => { return (dispatch, getState): void => {
const accountState = getState().abstractAccount;
const currentState = getState().sendForm; const currentState = getState().sendForm;
const isToken: boolean = currentState.token !== accountState.network;
const feeLevels: Array<FeeLevel> = getFeeLevels(currentState.coinSymbol, currentState.recommendedGasPrice, currentState.gasLimit); 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)
const state: State = { const state: State = {
@ -494,15 +506,15 @@ export const updateFeeLevels = (): any => {
}; };
if (currentState.setMax) { if (currentState.setMax) {
const account = getState().accounts.find(a => a.deviceState === currentState.deviceState && a.index === currentState.accountIndex && a.network === currentState.network); const account: ?Account = findAccount(getState().accounts, accountState.index, accountState.deviceState, accountState.network);
if (state.token !== state.network) { if (isToken) {
const tokenBalance: string = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === currentState.token).balance; const tokenBalance: string = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === currentState.token).balance;
state.amount = tokenBalance; state.amount = tokenBalance;
} else { } else {
state.amount = calculateMaxAmount(account.balance, state.gasPrice, state.gasLimit); state.amount = calculateMaxAmount(account.balance, state.gasPrice, state.gasLimit);
} }
} }
state.total = calculateTotal(state.token !== state.network ? '0' : state.amount, state.gasPrice, state.gasLimit); state.total = calculateTotal(isToken ? '0' : state.amount, state.gasPrice, state.gasLimit);
dispatch({ dispatch({
type: SEND.UPDATE_FEE_LEVELS, type: SEND.UPDATE_FEE_LEVELS,
@ -514,8 +526,10 @@ export const updateFeeLevels = (): any => {
export const onGasPriceChange = (gasPrice: string): any => { export const onGasPriceChange = (gasPrice: string): any => {
return (dispatch, getState): void => { return (dispatch, getState): void => {
const accountState = getState().abstractAccount;
const currentState = getState().sendForm; const currentState = getState().sendForm;
const isToken: boolean = currentState.token !== accountState.network;
const touched = { ...currentState.touched }; const touched = { ...currentState.touched };
touched.gasPrice = true; touched.gasPrice = true;
@ -534,8 +548,8 @@ export const onGasPriceChange = (gasPrice: string): any => {
state.selectedFeeLevel = customLevel; state.selectedFeeLevel = customLevel;
if (currentState.setMax) { if (currentState.setMax) {
const account = getState().accounts.find(a => a.deviceState === currentState.deviceState && a.index === currentState.accountIndex && a.network === currentState.network); const account: ?Account = findAccount(getState().accounts, accountState.index, accountState.deviceState, accountState.network);
if (state.token !== state.network) { if (isToken) {
const tokenBalance: string = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === currentState.token).balance; const tokenBalance: string = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === currentState.token).balance;
state.amount = tokenBalance; state.amount = tokenBalance;
} else { } else {
@ -544,7 +558,7 @@ export const onGasPriceChange = (gasPrice: string): any => {
} }
} }
state.total = calculateTotal(state.token !== state.network ? '0' : state.amount, state.gasPrice, state.gasLimit); state.total = calculateTotal(isToken ? '0' : state.amount, state.gasPrice, state.gasLimit);
dispatch({ dispatch({
type: SEND.GAS_PRICE_CHANGE, type: SEND.GAS_PRICE_CHANGE,
@ -556,7 +570,10 @@ export const onGasPriceChange = (gasPrice: string): any => {
export const onGasLimitChange = (gasLimit: string): any => { export const onGasLimitChange = (gasLimit: string): any => {
return (dispatch, getState): void => { return (dispatch, getState): void => {
const accountState = getState().abstractAccount;
const currentState = getState().sendForm; const currentState = getState().sendForm;
const isToken: boolean = currentState.token !== accountState.network;
const touched = { ...currentState.touched }; const touched = { ...currentState.touched };
touched.gasLimit = true; touched.gasLimit = true;
@ -568,15 +585,15 @@ export const onGasLimitChange = (gasLimit: string): any => {
}; };
if (gasLimit.match(numberRegExp) && state.gasPrice.match(numberRegExp)) { if (gasLimit.match(numberRegExp) && state.gasPrice.match(numberRegExp)) {
const customLevel = currentState.feeLevels.find(f => f.value === 'Custom'); const customLevel = state.feeLevels.find(f => f.value === 'Custom');
customLevel.label = `${ calculateFee(state.gasPrice, gasLimit) } ${ state.coinSymbol }`; customLevel.label = `${ calculateFee(currentState.gasPrice, gasLimit) } ${ state.coinSymbol }`;
state.selectedFeeLevel = customLevel; state.selectedFeeLevel = customLevel;
if (currentState.setMax) { if (state.setMax) {
const account = getState().accounts.find(a => a.deviceState === currentState.deviceState && a.index === currentState.accountIndex && a.network === currentState.network); const account: ?Account = findAccount(getState().accounts, accountState.index, accountState.deviceState, accountState.network);
if (state.token !== state.network) { if (isToken) {
const tokenBalance: string = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === currentState.token).balance; const tokenBalance: string = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === state.token).balance;
state.amount = tokenBalance; state.amount = tokenBalance;
} else { } else {
state.amount = calculateMaxAmount(account.balance, state.gasPrice, state.gasLimit); state.amount = calculateMaxAmount(account.balance, state.gasPrice, state.gasLimit);
@ -584,7 +601,7 @@ export const onGasLimitChange = (gasLimit: string): any => {
} }
} }
state.total = calculateTotal(state.token !== state.network ? '0' : state.amount, state.gasPrice, state.gasLimit); state.total = calculateTotal(isToken ? '0' : state.amount, state.gasPrice, state.gasLimit);
dispatch({ dispatch({
type: SEND.GAS_LIMIT_CHANGE, type: SEND.GAS_LIMIT_CHANGE,
@ -620,32 +637,30 @@ export const onSend = (): any => {
return async (dispatch, getState): Promise<any> => { return async (dispatch, getState): Promise<any> => {
const state: State = getState().sendForm; const accountState = getState().abstractAccount;
const web3instance = getState().web3.filter(w3 => w3.network === state.network)[0]; const currentState: State = getState().sendForm;
const web3instance = getState().web3.filter(w3 => w3.network === accountState.network)[0];
const web3 = web3instance.web3; const web3 = web3instance.web3;
const account: ?Account = findAccount(getState().accounts, accountState.index, accountState.deviceState, accountState.network);
const account = getState().accounts.find(a => a.deviceState === state.deviceState && a.index === state.accountIndex && a.network === state.network); const isToken: boolean = currentState.token !== accountState.network;
const address_n = account.addressPath; const address_n = account.addressPath;
let data: string = ''; let data: string = '';
let txAmount = web3.toHex(web3.toWei(state.amount, 'ether')); let txAmount = web3.toHex(web3.toWei(currentState.amount, 'ether'));
let txAddress = state.address; let txAddress = currentState.address;
if (state.network !== state.token) { if (isToken) {
const tokens = getState().tokens const t = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === currentState.token);
const t = tokens.find(t => t.ethAddress === account.address && t.symbol === state.token);
const contract = web3instance.erc20.at(t.address); const contract = web3instance.erc20.at(t.address);
data = contract.transfer.getData(state.address, state.amount, { data = contract.transfer.getData(currentState.address, currentState.amount, {
from: account.address, from: account.address,
gasLimit: state.gasLimit, gasLimit: currentState.gasLimit,
gasPrice: state.gasPrice gasPrice: currentState.gasPrice
}); });
txAmount = '0x00'; txAmount = '0x00';
txAddress = t.address; txAddress = t.address;
} }
const txData = { const txData = {
address_n, address_n,
// from: currentAddress.address // from: currentAddress.address
@ -655,8 +670,8 @@ export const onSend = (): any => {
//chainId: 3 // ropsten //chainId: 3 // ropsten
chainId: web3instance.chainId, chainId: web3instance.chainId,
nonce: web3.toHex(account.nonce), nonce: web3.toHex(account.nonce),
gasLimit: web3.toHex(state.gasLimit), gasLimit: web3.toHex(currentState.gasLimit),
gasPrice: web3.toHex( EthereumjsUnits.convert(state.gasPrice, 'gwei', 'wei') ), gasPrice: web3.toHex( EthereumjsUnits.convert(currentState.gasPrice, 'gwei', 'wei') ),
r: '', r: '',
s: '', s: '',
v: '' v: ''
@ -721,7 +736,7 @@ export const onSend = (): any => {
// console.log("---->GASSS", txData, gasLimit2.toString() ); // console.log("---->GASSS", txData, gasLimit2.toString() );
const { config } = getState().localStorage; const { config } = getState().localStorage;
const selectedCoin = config.coins.find(c => c.network === state.network); const selectedCoin = config.coins.find(c => c.network === currentState.network);
try { try {
const tx = new EthereumjsTx(txData); const tx = new EthereumjsTx(txData);
@ -731,8 +746,8 @@ export const onSend = (): any => {
dispatch({ dispatch({
type: SEND.TX_COMPLETE, type: SEND.TX_COMPLETE,
address: account, address: account,
token: state.token, token: currentState.token,
amount: state.amount, amount: currentState.amount,
txid, txid,
txData, txData,
}); });

View File

@ -15,20 +15,9 @@ import { findSelectedDevice } from '../reducers/TrezorConnectReducer';
export const init = (): any => { export const init = (): any => {
return (dispatch, getState): void => { return (dispatch, getState): void => {
const { location } = getState().router;
const urlParams = location.params;
const selected = findSelectedDevice( getState().connect );
if (!selected || !selected.state) return;
const state: State = { const state: State = {
...initialState, ...initialState,
deviceState: selected.state,
deviceId: selected.features.device_id,
deviceInstance: selected.instance,
accountIndex: parseInt(urlParams.address),
network: urlParams.network,
location: location.pathname,
}; };
dispatch({ dispatch({
@ -42,12 +31,12 @@ export const init = (): any => {
export const update = (newProps: any): any => { export const update = (newProps: any): any => {
return (dispatch, getState): void => { return (dispatch, getState): void => {
const { const {
summary, abstractAccount,
router router
} = getState(); } = getState();
const isLocationChanged: boolean = router.location.pathname !== summary.location; const isLocationChanged: boolean = router.location.pathname !== abstractAccount.location;
if (isLocationChanged || !summary.deviceState) { if (isLocationChanged) {
dispatch( init() ); dispatch( init() );
return; return;
} }

View File

@ -11,26 +11,21 @@ import { QRCode } from 'react-qr-svg';
import AbstractAccount from './account/AbstractAccount'; import AbstractAccount from './account/AbstractAccount';
import { Notification } from '../common/Notification'; import { Notification } from '../common/Notification';
import * as ReceiveActions from '../../actions/ReceiveActions'; import * as ReceiveActions from '../../actions/ReceiveActions';
import * as AbstractAccountActions from '../../actions/AbstractAccountActions';
class Receive extends AbstractAccount { class Receive extends AbstractAccount {
render() { render() {
return super.render(this.props.receive) || _render(this.props, this.device, this.account, this.deviceStatusNotification); return super.render() || _render(this.props, this.device, this.account, this.deviceStatusNotification);
} }
} }
const _render = (props: any, device, account, deviceStatusNotification): any => { const _render = (props: any, device, account, deviceStatusNotification): any => {
const { const {
network,
deviceState,
accountIndex,
addressVerified, addressVerified,
addressUnverified, addressUnverified,
} = props.receive; } = props.receive;
// const device = props.devices.find(d => d.state === deviceState);
// const account = props.accounts.find(a => a.deviceState === deviceState && a.index === accountIndex && a.network === network);
let qrCode = null; let qrCode = null;
let address = `${account.address.substring(0, 20)}...`; let address = `${account.address.substring(0, 20)}...`;
let className = 'address hidden'; let className = 'address hidden';
@ -91,6 +86,7 @@ const _render = (props: any, device, account, deviceStatusNotification): any =>
const mapStateToProps = (state, own) => { const mapStateToProps = (state, own) => {
return { return {
abstractAccount: state.abstractAccount,
location: state.router.location, location: state.router.location,
devices: state.connect.devices, devices: state.connect.devices,
accounts: state.accounts, accounts: state.accounts,
@ -101,6 +97,7 @@ const mapStateToProps = (state, own) => {
const mapDispatchToProps = (dispatch) => { const mapDispatchToProps = (dispatch) => {
return { return {
abstractAccountActions: bindActionCreators(AbstractAccountActions, dispatch),
initAccount: bindActionCreators(ReceiveActions.init, dispatch), initAccount: bindActionCreators(ReceiveActions.init, dispatch),
updateAccount: bindActionCreators(ReceiveActions.update, dispatch), updateAccount: bindActionCreators(ReceiveActions.update, dispatch),
disposeAccount: bindActionCreators(ReceiveActions.dispose, dispatch), disposeAccount: bindActionCreators(ReceiveActions.dispose, dispatch),

View File

@ -32,6 +32,7 @@ export default class AbstractAccount extends Component {
} }
componentDidMount() { componentDidMount() {
this.props.abstractAccountActions.init();
this.props.initAccount(); this.props.initAccount();
} }
@ -41,10 +42,12 @@ export default class AbstractAccount extends Component {
this.account = null; this.account = null;
this.deviceStatusNotification = null; this.deviceStatusNotification = null;
this.props.abstractAccountActions.update();
this.props.updateAccount(); this.props.updateAccount();
} }
componentWillUnmount() { componentWillUnmount() {
this.props.abstractAccountActions.dispose();
this.props.disposeAccount(); this.props.disposeAccount();
this.device = null; this.device = null;
@ -53,21 +56,22 @@ export default class AbstractAccount extends Component {
this.deviceStatusNotification = null; this.deviceStatusNotification = null;
} }
render(state: any): any { render(): any {
const props = this.props; const props = this.props;
const state = props.abstractAccount;
if (!state.deviceState) { if (!state.deviceState) {
return (<section><Notification className="info" title="Loading device" /></section>); return (<section><Notification className="info" title="Loading device" /></section>);
} }
const device = findDevice(this.props.devices, state.deviceState, state.deviceId, state.deviceInstance); const device = findDevice(props.devices, state.deviceState, state.deviceId, state.deviceInstance);
if (!device) { if (!device) {
return (<section>Device with state {state.deviceState} not found</section>); return (<section>Device with state {state.deviceState} not found</section>);
} }
const discovery = props.discovery.find(d => d.deviceState === device.state && d.network === state.network); const discovery = props.discovery.find(d => d.deviceState === device.state && d.network === state.network);
const account = props.accounts.find(a => a.deviceState === state.deviceState && a.index === state.accountIndex && a.network === state.network); const account = props.accounts.find(a => a.deviceState === state.deviceState && a.index === state.index && a.network === state.network);
let deviceStatusNotification = null; let deviceStatusNotification = null;
if (!account) { if (!account) {

View File

@ -6,8 +6,8 @@ import Tooltip from 'rc-tooltip';
const AdvancedForm = (props: any): any => { const AdvancedForm = (props: any): any => {
const { network } = props.abstractAccount;
const { const {
network,
token, token,
gasPrice, gasPrice,
gasLimit, gasLimit,

View File

@ -11,23 +11,20 @@ import AbstractAccount from '../account/AbstractAccount';
export default class Send extends AbstractAccount { export default class Send extends AbstractAccount {
render() { render() {
return super.render(this.props.sendForm) || _render(this.props, this.device, this.discovery, this.account, this.deviceStatusNotification); return super.render() || _render(this.props, this.device, this.discovery, this.account, this.deviceStatusNotification);
} }
} }
const _render = (props: any, device, discovery, account, deviceStatusNotification): any => { const _render = (props: any, device, discovery, account, deviceStatusNotification): any => {
// const device = props.devices.find(device => device.state === props.sendForm.deviceState);
// const discovery = props.discovery.find(d => d.deviceState === device.state && d.network === props.sendForm.network);
// const account = props.accounts.find(a => a.deviceState === props.sendForm.deviceState && a.index === props.sendForm.accountIndex && a.network === props.sendForm.network);
const addressTokens = props.tokens.filter(t => t.ethAddress === account.address); const addressTokens = props.tokens.filter(t => t.ethAddress === account.address);
const { network } = props.abstractAccount;
const { const {
address, address,
amount, amount,
setMax, setMax,
network,
coinSymbol, coinSymbol,
token, token,
feeLevels, feeLevels,
@ -54,7 +51,7 @@ const _render = (props: any, device, discovery, account, deviceStatusNotificatio
const { config } = props.localStorage; const { config } = props.localStorage;
const selectedCoin = config.coins.find(c => c.network === network); const selectedCoin = config.coins.find(c => c.network === network);
const fiatRate = props.fiat.find(f => f.network === selectedCoin.network); const fiatRate = props.fiat.find(f => f.network === network);
const tokens = addressTokens.map(t => { const tokens = addressTokens.map(t => {
return { value: t.symbol, label: t.symbol }; return { value: t.symbol, label: t.symbol };

View File

@ -6,10 +6,12 @@ import { bindActionCreators } from 'redux';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import * as SendFormActions from '../../../actions/SendFormActions'; import * as SendFormActions from '../../../actions/SendFormActions';
import * as AbstractAccountActions from '../../../actions/AbstractAccountActions';
import SendForm from './SendForm'; import SendForm from './SendForm';
const mapStateToProps = (state, own) => { const mapStateToProps = (state, own) => {
return { return {
abstractAccount: state.abstractAccount,
location: state.router.location, location: state.router.location,
devices: state.connect.devices, devices: state.connect.devices,
accounts: state.accounts, accounts: state.accounts,
@ -24,6 +26,7 @@ const mapStateToProps = (state, own) => {
const mapDispatchToProps = (dispatch) => { const mapDispatchToProps = (dispatch) => {
return { return {
abstractAccountActions: bindActionCreators(AbstractAccountActions, dispatch),
sendFormActions: bindActionCreators(SendFormActions, dispatch), sendFormActions: bindActionCreators(SendFormActions, dispatch),
initAccount: bindActionCreators(SendFormActions.init, dispatch), initAccount: bindActionCreators(SendFormActions.init, dispatch),
updateAccount: bindActionCreators(SendFormActions.update, dispatch), updateAccount: bindActionCreators(SendFormActions.update, dispatch),

View File

@ -14,17 +14,13 @@ import { findDevice } from '../../../utils/reducerUtils';
export default class Summary extends AbstractAccount { export default class Summary extends AbstractAccount {
render() { render() {
console.warn("RENDER SUMMARY!", this.device, this.discovery, this) return super.render() || _render(this.props, this.device, this.discovery, this.account, this.deviceStatusNotification);
return super.render(this.props.summary) || _render(this.props, this.device, this.discovery, this.account, this.deviceStatusNotification);
} }
} }
const _render = (props: any, device, discovery, account, deviceStatusNotification): any => { const _render = (props: any, device, discovery, account, deviceStatusNotification): any => {
//const device = props.devices.find(d => d.state === props.summary.deviceState && d.features.device_id === props.summary.deviceId); const abstractAccount = props.abstractAccount;
// const device = findDevice(props.devices, props.summary.deviceState, props.summary.deviceId);
// const discovery = props.discovery.find(d => d.deviceState === device.state && d.network === props.summary.network);
//const account = props.accounts.find(a => a.deviceState === props.summary.deviceState && a.index === props.summary.accountIndex && a.network === props.summary.network);
const tokens = props.tokens.filter(t => t.ethAddress === account.address); const tokens = props.tokens.filter(t => t.ethAddress === account.address);
return ( return (
@ -32,12 +28,12 @@ const _render = (props: any, device, discovery, account, deviceStatusNotificatio
<section className="summary"> <section className="summary">
{ deviceStatusNotification } { deviceStatusNotification }
<h2 className={ `summary-header ${props.summary.network}` }>Address #{ parseInt(props.match.params.address) + 1 }</h2> <h2 className={ `summary-header ${abstractAccount.network}` }>Address #{ parseInt(abstractAccount.index) + 1 }</h2>
<SummaryDetails <SummaryDetails
summary={ props.summary } summary={ props.summary }
balance={ account.balance } balance={ account.balance }
network={ props.summary.network } network={ abstractAccount.network }
fiat={ props.fiat } fiat={ props.fiat }
localStorage={ props.localStorage } localStorage={ props.localStorage }
onToggle={ props.summaryActions.onDetailsToggle } /> onToggle={ props.summaryActions.onDetailsToggle } />

View File

@ -6,15 +6,19 @@ import { bindActionCreators } from 'redux';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import Summary from './Summary'; import Summary from './Summary';
import * as AbstractAccountActions from '../../../actions/AbstractAccountActions';
import * as SummaryActions from '../../../actions/SummaryActions'; import * as SummaryActions from '../../../actions/SummaryActions';
const mapStateToProps = (state, own) => { const mapStateToProps = (state, own) => {
return { return {
abstractAccount: state.abstractAccount,
location: state.router.location, location: state.router.location,
devices: state.connect.devices, devices: state.connect.devices,
accounts: state.accounts, accounts: state.accounts,
discovery: state.discovery, discovery: state.discovery,
tokens: state.tokens, tokens: state.tokens,
summary: state.summary, summary: state.summary,
fiat: state.fiat, fiat: state.fiat,
localStorage: state.localStorage localStorage: state.localStorage
@ -23,6 +27,7 @@ const mapStateToProps = (state, own) => {
const mapDispatchToProps = (dispatch) => { const mapDispatchToProps = (dispatch) => {
return { return {
abstractAccountActions: bindActionCreators(AbstractAccountActions, dispatch),
summaryActions: bindActionCreators(SummaryActions, dispatch), summaryActions: bindActionCreators(SummaryActions, dispatch),
initAccount: bindActionCreators(SummaryActions.init, dispatch), initAccount: bindActionCreators(SummaryActions.init, dispatch),
updateAccount: bindActionCreators(SummaryActions.update, dispatch), updateAccount: bindActionCreators(SummaryActions.update, dispatch),

View File

@ -6,7 +6,9 @@ import * as CONNECT from '../actions/constants/TrezorConnect';
export type State = { export type State = {
+index: number; +index: number;
+ch: ?string; +deviceState: ?string;
+deviceId: ?string;
+deviceInstance: ?string;
+network: string; +network: string;
location: string; location: string;
} }
@ -14,7 +16,10 @@ export type State = {
export const initialState: State = { export const initialState: State = {
index: 0, index: 0,
deviceState: null, deviceState: null,
deviceId: null,
deviceInstance: null,
network: '', network: '',
location: '',
}; };
@ -25,12 +30,6 @@ export default (state: State = initialState, action: any): State => {
case ACCOUNT.INIT : case ACCOUNT.INIT :
return action.state; return action.state;
case CONNECT.DEVICE_STATE_EXCEPTION :
return {
...state,
deviceStateError: true
}
case ACCOUNT.DISPOSE : case ACCOUNT.DISPOSE :
return initialState; return initialState;

View File

@ -18,6 +18,10 @@ export type Account = {
const initialState: Array<Account> = []; const initialState: Array<Account> = [];
export const findAccount = (state: Array<Account>, index: number, deviceState: string, network: string): ?Account => {
return state.find(a => a.deviceState === deviceState && a.index === index && a.network === network);
}
const createAccount = (state: Array<Account>, action: any): Array<Account> => { const createAccount = (state: Array<Account>, action: any): Array<Account> => {
// TODO check with device_id // TODO check with device_id

View File

@ -4,23 +4,11 @@
import * as RECEIVE from '../actions/constants/receive'; import * as RECEIVE from '../actions/constants/receive';
export type State = { export type State = {
+deviceState: ?string;
+deviceId: ?string;
+deviceInstance: ?string;
+accountIndex: ?number;
+network: ?string;
location: string;
addressVerified: boolean; addressVerified: boolean;
adressUnverified: boolean; adressUnverified: boolean;
} }
export const initialState: State = { export const initialState: State = {
deviceState: null,
deviceId: null,
deviceInstance: null,
accountIndex: null,
network: null,
location: '',
addressVerified: false, addressVerified: false,
addressUnverified: false, addressUnverified: false,
}; };

View File

@ -10,18 +10,10 @@ import BigNumber from 'bignumber.js';
import { getFeeLevels } from '../actions/SendFormActions'; import { getFeeLevels } from '../actions/SendFormActions';
export type State = { export type State = {
+deviceState: ?string;
+deviceId: ?string;
+deviceInstance: ?string;
+accountIndex: number;
+network: string;
+coinSymbol: string; +coinSymbol: string;
token: string; token: string;
location: string;
balanceNeedUpdate: boolean; balanceNeedUpdate: boolean;
// form fields // form fields
advanced: boolean; advanced: boolean;
untouched: boolean; // set to true when user made any changes in form untouched: boolean; // set to true when user made any changes in form
@ -52,14 +44,8 @@ export type FeeLevel = {
export const initialState: State = { export const initialState: State = {
deviceState: null,
deviceId: null,
deviceInstance: null,
accountIndex: 0,
network: '',
coinSymbol: '', coinSymbol: '',
token: '', token: '',
location: '',
advanced: false, advanced: false,
untouched: true, untouched: true,

View File

@ -4,25 +4,11 @@
import * as SUMMARY from '../actions/constants/summary'; import * as SUMMARY from '../actions/constants/summary';
export type State = { export type State = {
+deviceState: ?string;
+deviceId: ?string;
+deviceInstance: ?string;
+accountIndex: ?number;
+network: ?string;
location: string;
details: boolean; details: boolean;
selectedToken: any; selectedToken: any;
} }
export const initialState: State = { export const initialState: State = {
deviceState: null,
deviceId: null,
deviceInstance: null,
accountIndex: null,
network: null,
location: '',
details: true, details: true,
selectedToken: null selectedToken: null
}; };