From 1007477bae596a6b1a9dd213e89a153763fc65c5 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Thu, 10 May 2018 12:39:49 +0200 Subject: [PATCH] refactor sendForm.token to sendForm.selectedCurrency --- src/js/actions/SendFormActions.js | 64 ++++++++----------- src/js/components/modal/ConfirmSignTx.js | 4 +- src/js/components/wallet/send/AdvancedForm.js | 6 +- .../wallet/send/PendingTransactions.js | 58 ++++++++++------- src/js/components/wallet/send/SendForm.js | 21 +++--- src/js/components/wallet/summary/Summary.js | 3 +- src/js/reducers/PendingTxReducer.js | 19 +++--- src/js/reducers/SendFormReducer.js | 4 +- src/js/reducers/TokensReducer.js | 5 ++ src/js/services/LocalStorageService.js | 3 +- 10 files changed, 97 insertions(+), 90 deletions(-) diff --git a/src/js/actions/SendFormActions.js b/src/js/actions/SendFormActions.js index 99572346..686f7793 100644 --- a/src/js/actions/SendFormActions.js +++ b/src/js/actions/SendFormActions.js @@ -35,14 +35,16 @@ import type { Token } from '../reducers/TokensReducer'; import type { State, FeeLevel } from '../reducers/SendFormReducer'; import type { Account } from '../reducers/AccountsReducer'; -export type SendFormAction = { +export type SendTxAction = { type: typeof SEND.TX_COMPLETE, account: Account, - token: string, + selectedCurrency: string, amount: string, txid: string, txData: any, -} | { +}; + +export type SendFormAction = SendTxAction | { type: typeof SEND.INIT, state: State } | { @@ -152,18 +154,6 @@ export const getFeeLevels = (symbol: string, gasPrice: BigNumber | string, gasLi ] } -// 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; -// } -// } - // initialize component export const init = (): ThunkAction => { @@ -200,7 +190,7 @@ export const init = (): ThunkAction => { ...initialState, network: coin.network, coinSymbol: coin.symbol, - token: coin.symbol, + selectedCurrency: coin.symbol, feeLevels, selectedFeeLevel: feeLevels.find(f => f.value === 'Normal'), recommendedGasPrice: gasPrice.toString(), @@ -274,8 +264,8 @@ export const validation = (): ThunkAction => { let decimalRegExp: RegExp; - if (state.token !== accountState.network) { - const token = getState().tokens.find(t => t.ethAddress === account.address && t.symbol === state.token); + if (state.selectedCurrency !== state.coinSymbol) { + const token = findToken(getState().tokens, account.address, state.selectedCurrency, account.deviceState); if (token) { if (parseInt(token.decimals) > 0) { //decimalRegExp = new RegExp('^(0|0\\.([0-9]{0,' + token.decimals + '})?|[1-9]+\\.?([0-9]{0,' + token.decimals + '})?|\\.[0-9]{1,' + token.decimals + '})$'); @@ -288,7 +278,7 @@ export const validation = (): ThunkAction => { if (!state.amount.match(decimalRegExp)) { errors.amount = `Maximum ${ token.decimals} decimals allowed`; } else if (new BigNumber(state.total).greaterThan(account.balance)) { - errors.amount = `Not enough ${ state.coinSymbol.toUpperCase() } to cover transaction fee`; + errors.amount = `Not enough ${ state.coinSymbol } to cover transaction fee`; } else if (new BigNumber(state.amount).greaterThan(token.balance)) { errors.amount = 'Not enough funds'; } else if (new BigNumber(state.amount).lessThanOrEqualTo('0')) { @@ -340,7 +330,7 @@ export const validation = (): ThunkAction => { } // valid data - if (state.touched.data && accountState.network === state.token && state.data.length > 0) { + if (state.touched.data && state.data.length > 0) { const re = /^[0-9A-Fa-f]+$/g; //const re = /^[0-9A-Fa-f]{6}$/g; if (!re.test(state.data)) { @@ -389,7 +379,7 @@ export const onAmountChange = (amount: string): ThunkAction => { const accountState: AccountState = getState().abstractAccount; const currentState: State = getState().sendForm; - const isToken: boolean = currentState.token !== currentState.coinSymbol; + const isToken: boolean = currentState.selectedCurrency !== currentState.coinSymbol; const touched = { ...currentState.touched }; touched.amount = true; const total: string = calculateTotal(isToken ? '0' : amount, currentState.gasPrice, currentState.gasLimit); @@ -428,11 +418,12 @@ export const onCurrencyChange = (currency: any): ThunkAction => { let gasLimit: string = ''; let amount: string = currentState.amount; let total: string; - + console.warn("SEL", currency, currentState.coinSymbol) if (isToken) { gasLimit = coin.defaultGasLimitTokens.toString(); if (currentState.setMax) { const token: ?Token = findToken(getState().tokens, account.address, currency.value, accountState.deviceState); + console.warn("SEL", token, currency.value) if (!token) return; amount = token.balance; } @@ -451,7 +442,7 @@ export const onCurrencyChange = (currency: any): ThunkAction => { const state: State = { ...currentState, - token: currency.value, + selectedCurrency: currency.value, amount, total, feeLevels, @@ -473,7 +464,7 @@ export const onSetMax = (): ThunkAction => { return (dispatch: Dispatch, getState: GetState): void => { const accountState: AccountState = getState().abstractAccount; const currentState: State = getState().sendForm; - const isToken: boolean = currentState.token !== currentState.coinSymbol; + const isToken: boolean = currentState.selectedCurrency !== currentState.coinSymbol; const touched = { ...currentState.touched }; touched.amount = true; @@ -487,7 +478,7 @@ export const onSetMax = (): ThunkAction => { let total: string = currentState.total; if (!currentState.setMax) { if (isToken) { - const token: ?Token = findToken(getState().tokens, account.address, currentState.token, accountState.deviceState); + const token: ?Token = findToken(getState().tokens, account.address, currentState.selectedCurrency, accountState.deviceState); if (!token) return; amount = token.balance; total = calculateTotal('0', currentState.gasPrice, currentState.gasLimit); @@ -518,7 +509,7 @@ export const onFeeLevelChange = (feeLevel: FeeLevel): ThunkAction => { return (dispatch: Dispatch, getState: GetState): void => { const accountState: AccountState = getState().abstractAccount; const currentState: State = getState().sendForm; - const isToken: boolean = currentState.token !== currentState.coinSymbol; + const isToken: boolean = currentState.selectedCurrency !== currentState.coinSymbol; const { config } = getState().localStorage; if (!config) return; @@ -550,7 +541,7 @@ export const onFeeLevelChange = (feeLevel: FeeLevel): ThunkAction => { if (!account) return; if (isToken) { - const token: ?Token = findToken(getState().tokens, account.address, currentState.token, accountState.deviceState); + const token: ?Token = findToken(getState().tokens, account.address, currentState.selectedCurrency, accountState.deviceState); if (!token) return; state.amount = token.balance; } else { @@ -571,7 +562,7 @@ export const updateFeeLevels = (): ThunkAction => { return (dispatch: Dispatch, getState: GetState): void => { const accountState: AccountState = getState().abstractAccount; const currentState: State = getState().sendForm; - const isToken: boolean = currentState.token !== currentState.coinSymbol; + const isToken: boolean = currentState.selectedCurrency !== currentState.coinSymbol; const feeLevels: Array = getFeeLevels(currentState.coinSymbol, currentState.recommendedGasPrice, currentState.gasLimit); const selectedFeeLevel: ?FeeLevel = feeLevels.find(f => f.value === currentState.selectedFeeLevel.value); @@ -590,7 +581,7 @@ export const updateFeeLevels = (): ThunkAction => { const account: ?Account = findAccount(getState().accounts, accountState.index, accountState.deviceState, accountState.network); if (!account) return; if (isToken) { - const token: ?Token = findToken(getState().tokens, account.address, state.token, accountState.deviceState); + const token: ?Token = findToken(getState().tokens, account.address, state.selectedCurrency, accountState.deviceState); if (!token) return; const tokenBalance: string = token.balance; state.amount = tokenBalance; @@ -612,7 +603,7 @@ export const onGasPriceChange = (gasPrice: string): ThunkAction => { return (dispatch: Dispatch, getState: GetState): void => { const accountState: AccountState = getState().abstractAccount; const currentState: State = getState().sendForm; - const isToken: boolean = currentState.token !== accountState.network; + const isToken: boolean = currentState.selectedCurrency !== accountState.network; const touched = { ...currentState.touched }; touched.gasPrice = true; @@ -636,7 +627,7 @@ export const onGasPriceChange = (gasPrice: string): ThunkAction => { const account: ?Account = findAccount(getState().accounts, accountState.index, accountState.deviceState, accountState.network); if (!account) return; if (isToken) { - const token: ?Token = findToken(getState().tokens, account.address, state.token, accountState.deviceState); + const token: ?Token = findToken(getState().tokens, account.address, state.selectedCurrency, accountState.deviceState); if (!token) return; const tokenBalance: string = token.balance; state.amount = tokenBalance; @@ -660,7 +651,7 @@ export const onGasLimitChange = (gasLimit: string): ThunkAction => { return (dispatch: Dispatch, getState: GetState): void => { const accountState: AccountState = getState().abstractAccount; const currentState: State = getState().sendForm; - const isToken: boolean = currentState.token !== currentState.coinSymbol; + const isToken: boolean = currentState.selectedCurrency !== currentState.coinSymbol; const touched = { ...currentState.touched }; touched.gasLimit = true; @@ -684,7 +675,7 @@ export const onGasLimitChange = (gasLimit: string): ThunkAction => { if (!account) return; if (isToken) { - const token: ?Token = findToken(getState().tokens, account.address, state.token, accountState.deviceState); + const token: ?Token = findToken(getState().tokens, account.address, state.selectedCurrency, accountState.deviceState); if (!token) return; const tokenBalance: string = token.balance; state.amount = tokenBalance; @@ -735,7 +726,7 @@ export const onSend = (): AsyncAction => { const account: ?Account = findAccount(getState().accounts, accountState.index, accountState.deviceState, accountState.network); if (!account || !web3instance) return; - const isToken: boolean = currentState.token !== currentState.coinSymbol; + const isToken: boolean = currentState.selectedCurrency !== currentState.coinSymbol; const web3 = web3instance.web3; const address_n = account.addressPath; @@ -744,8 +735,7 @@ export const onSend = (): AsyncAction => { 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 token: ?Token = findToken(getState().tokens, account.address, currentState.token, accountState.deviceState); + const token: ?Token = findToken(getState().tokens, account.address, currentState.selectedCurrency, accountState.deviceState); if (!token) return; const contract = web3instance.erc20.at(token.address); @@ -842,7 +832,7 @@ export const onSend = (): AsyncAction => { dispatch({ type: SEND.TX_COMPLETE, account: account, - token: currentState.token, + selectedCurrency: currentState.selectedCurrency, amount: currentState.amount, txid, txData, diff --git a/src/js/components/modal/ConfirmSignTx.js b/src/js/components/modal/ConfirmSignTx.js index f7647e03..4ffe77c2 100644 --- a/src/js/components/modal/ConfirmSignTx.js +++ b/src/js/components/modal/ConfirmSignTx.js @@ -10,7 +10,7 @@ const Confirmation = (props: Props) => { address, network, coinSymbol, - token, + selectedCurrency, total, selectedFeeLevel } = props.sendForm; @@ -23,7 +23,7 @@ const Confirmation = (props: Props) => {
-

{ `${amount} ${ token }` }

+

{ `${amount} ${ selectedCurrency }` }

{ address }

diff --git a/src/js/components/wallet/send/AdvancedForm.js b/src/js/components/wallet/send/AdvancedForm.js index 10e5e533..6515e0f4 100644 --- a/src/js/components/wallet/send/AdvancedForm.js +++ b/src/js/components/wallet/send/AdvancedForm.js @@ -10,7 +10,8 @@ const AdvancedForm = (props: Props) => { const { network } = props.abstractAccount; const { - token, + coinSymbol, + selectedCurrency, gasPrice, gasLimit, data, @@ -117,7 +118,8 @@ const AdvancedForm = (props: Props) => { - + + {/* */} { errors.data ? ({ errors.data }) : null }
diff --git a/src/js/components/wallet/send/PendingTransactions.js b/src/js/components/wallet/send/PendingTransactions.js index c0386fea..c4b66594 100644 --- a/src/js/components/wallet/send/PendingTransactions.js +++ b/src/js/components/wallet/send/PendingTransactions.js @@ -5,44 +5,45 @@ import React from 'react'; import ColorHash from 'color-hash'; import ScaleText from 'react-scale-text'; +import { findAccountTokens } from '../../../reducers/TokensReducer'; + import type { Props as ParentProps } from './index'; import type { Coin } from '../../../reducers/LocalStorageReducer'; import type { Account } from '../../../reducers/AccountsReducer'; +import type { Token } from '../../../reducers/TokensReducer'; type Props = ParentProps & { account: Account, selectedCoin: Coin - // account: any } -const PendingTransactions = (props: Props) => { +type Style = { + +color: string, + +background: string, + +borderColor: string +} +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 account = props.account; const pending = props.pending.filter(p => p.network === account.network && p.address === account.address); if (pending.length < 1) return null; - const tokens = props.tokens.filter(t => t.ethAddress === account.address && t.network === account.network); + const tokens: Array = findAccountTokens(props.tokens, account); - const bgColor = new ColorHash({lightness: 0.7}); - const textColor = new ColorHash(); + const bgColorFactory = new ColorHash({lightness: 0.7}); + const textColorFactory = new ColorHash(); - const pendings = pending.map((tx, i) => { + const pendingTxs = pending.map((tx, i) => { - let iconColor, symbol, name; - - if (tx.token !== props.selectedCoin.symbol) { - const token = tokens.find(t => t.symbol === tx.token); - if (token) { - iconColor = { - color: textColor.hex(token.name), - background: bgColor.hex(token.name), - borderColor: bgColor.hex(token.name) - } - symbol = token.symbol.toUpperCase(); - name = token.name; - } else { + let iconColor: Style; + let symbol: string; + let name: string; + const isSmartContractTx: boolean = tx.currency !== props.selectedCoin.symbol; + if (isSmartContractTx) { + const token: ?Token = tokens.find(t => t.symbol === tx.currency); + if (!token) { iconColor = { color: '#ffffff', background: '#000000', @@ -50,12 +51,21 @@ const PendingTransactions = (props: Props) => { } symbol = "Unknown"; name = "Unknown"; + } else { + const bgColor: string = bgColorFactory.hex(token.name); + iconColor = { + color: textColorFactory.hex(token.name), + background: bgColor, + borderColor: bgColor + } + symbol = token.symbol.toUpperCase(); + name = token.name; } } else { iconColor = { - color: textColor.hex(tx.network), - background: bgColor.hex(tx.network), - borderColor: bgColor.hex(tx.network) + color: textColorFactory.hex(tx.network), + background: bgColorFactory.hex(tx.network), + borderColor: bgColorFactory.hex(tx.network) } symbol = props.selectedCoin.symbol; name = props.selectedCoin.name; @@ -80,7 +90,7 @@ const PendingTransactions = (props: Props) => { return (

Pending transactions

- { pendings } + { pendingTxs }
) } diff --git a/src/js/components/wallet/send/SendForm.js b/src/js/components/wallet/send/SendForm.js index cc41e8a2..9522b1a0 100644 --- a/src/js/components/wallet/send/SendForm.js +++ b/src/js/components/wallet/send/SendForm.js @@ -8,6 +8,7 @@ import PendingTransactions from './PendingTransactions'; import { FeeSelectValue, FeeSelectOption } from './FeeSelect'; import { Notification } from '../../common/Notification'; import AbstractAccount from '../account/AbstractAccount'; +import { findAccountTokens } from '../../../reducers/TokensReducer'; import type { Props } from './index'; import type { AccountState } from '../account/AbstractAccount'; @@ -30,7 +31,7 @@ const _render = (props: Props, state: AccountState): React$Element => { if (!device || !account || !discovery) return
; - const addressTokens = props.tokens.filter(t => t.ethAddress === account.address); + const tokens = findAccountTokens(props.tokens, account); const { network } = props.abstractAccount; const { @@ -38,7 +39,7 @@ const _render = (props: Props, state: AccountState): React$Element => { amount, setMax, coinSymbol, - token, + selectedCurrency, feeLevels, selectedFeeLevel, gasPriceNeedsUpdate, @@ -63,10 +64,10 @@ const _render = (props: Props, state: AccountState): React$Element => { const selectedCoin = props.abstractAccount.coin; const fiatRate = props.fiat.find(f => f.network === network); - const tokens = addressTokens.map(t => { + const tokensSelectData = tokens.map(t => { return { value: t.symbol, label: t.symbol }; }); - tokens.unshift({ value: selectedCoin.symbol, label: selectedCoin.symbol }); + tokensSelectData.unshift({ value: selectedCoin.symbol, label: selectedCoin.symbol }); const setMaxClassName: string = setMax ? 'set-max enabled' : 'set-max'; @@ -88,9 +89,9 @@ const _render = (props: Props, state: AccountState): React$Element => { let buttonDisabled: boolean = Object.keys(errors).length > 0 || total === '0' || amount.length === 0 || address.length === 0 || sending; let buttonLabel: string = 'Send'; - if (network !== token && amount.length > 0 && !errors.amount) { - buttonLabel += ` ${amount} ${ token.toUpperCase() }` - } else if (network === token && total !== '0') { + if (coinSymbol !== selectedCurrency && amount.length > 0 && !errors.amount) { + buttonLabel += ` ${amount} ${ selectedCurrency.toUpperCase() }` + } else if (coinSymbol === selectedCurrency && total !== '0') { buttonLabel += ` ${total} ${ selectedCoin.symbol }`; } @@ -155,10 +156,10 @@ const _render = (props: Props, state: AccountState): React$Element => { searchable={ false } clearable= { false } multi={ false } - value={ token } - disabled={ tokens.length < 2 } + value={ selectedCurrency } + disabled={ tokensSelectData.length < 2 } onChange={ onCurrencyChange } - options={ tokens } /> + options={ tokensSelectData } /> { errors.amount ? ({ errors.amount }) : null } { warnings.amount ? ({ warnings.amount }) : null } diff --git a/src/js/components/wallet/summary/Summary.js b/src/js/components/wallet/summary/Summary.js index f29e5e7e..debe3044 100644 --- a/src/js/components/wallet/summary/Summary.js +++ b/src/js/components/wallet/summary/Summary.js @@ -18,6 +18,7 @@ import type { TrezorDevice } from '../../../flowtype'; import type { NetworkToken } from '../../../reducers/LocalStorageReducer'; import type { Account } from '../../../reducers/AccountsReducer'; import type { Discovery } from '../../../reducers/DiscoveryReducer'; +import { findAccountTokens } from '../../../reducers/TokensReducer'; export default class Summary extends AbstractAccount { render() { @@ -36,7 +37,7 @@ const _render = (props: Props, state: AccountState): React$Element => { if (!device || !account) return
; const abstractAccount = props.abstractAccount; - const tokens = props.tokens.filter(t => t.ethAddress === account.address && t.network === account.network && t.deviceState === abstractAccount.deviceState); + const tokens = findAccountTokens(props.tokens, account); return ( diff --git a/src/js/reducers/PendingTxReducer.js b/src/js/reducers/PendingTxReducer.js index 8fa55f5e..98c61ea8 100644 --- a/src/js/reducers/PendingTxReducer.js +++ b/src/js/reducers/PendingTxReducer.js @@ -6,11 +6,12 @@ import * as SEND from '../actions/constants/send'; import * as WEB3 from '../actions/constants/web3'; import type { Action } from '../flowtype'; +import type { SendTxAction } from '../actions/SendFormActions'; export type PendingTx = { +id: string; +network: string; - +token: string; + +currency: string; +amount: string; +address: string; } @@ -19,24 +20,20 @@ export type State = Array; const initialState: State = []; -const add = (state: State, action: any) => { +const add = (state: State, action: SendTxAction): State => { const newState = [ ...state ]; newState.push({ id: action.txid, network: action.account.network, - address: action.account.address, - token: action.token, + currency: action.selectedCurrency, amount: action.amount, + address: action.account.address, }); return newState; } -const remove = (state: State, action: any) => { - return state.filter(tx => tx.id !== action.tx.id); -} - -const fromStorage = (state: State, action: any) => { - return state.filter(tx => tx.id !== action.tx.id); +const remove = (state: State, id: string): State => { + return state.filter(tx => tx.id !== id); } export default function pending(state: State = initialState, action: Action): State { @@ -47,7 +44,7 @@ export default function pending(state: State = initialState, action: Action): St return add(state, action); case PENDING.TX_RESOLVED : - return remove(state, action); + return remove(state, action.tx.id); case PENDING.FROM_STORAGE : return action.payload; diff --git a/src/js/reducers/SendFormReducer.js b/src/js/reducers/SendFormReducer.js index 5fcbb77b..f1907b57 100644 --- a/src/js/reducers/SendFormReducer.js +++ b/src/js/reducers/SendFormReducer.js @@ -18,7 +18,7 @@ import type { export type State = { +network: string; +coinSymbol: string; - token: string; + selectedCurrency: string; balanceNeedUpdate: boolean; // form fields @@ -53,7 +53,7 @@ export type FeeLevel = { export const initialState: State = { network: '', coinSymbol: '', - token: '', + selectedCurrency: '', advanced: false, untouched: true, diff --git a/src/js/reducers/TokensReducer.js b/src/js/reducers/TokensReducer.js index 165e9358..3edaf681 100644 --- a/src/js/reducers/TokensReducer.js +++ b/src/js/reducers/TokensReducer.js @@ -5,6 +5,7 @@ import * as CONNECT from '../actions/constants/TrezorConnect'; import * as TOKEN from '../actions/constants/token'; import type { Action, TrezorDevice } from '../flowtype'; +import type { Account } from './AccountsReducer'; export type Token = { loaded: boolean; @@ -27,6 +28,10 @@ export const findToken = (state: Array, address: string, symbol: string, return state.find(t => t.ethAddress === address && t.symbol === symbol && t.deviceState === deviceState); } +export const findAccountTokens = (state: Array, account: Account): Array => { + return state.filter(t => t.ethAddress === account.address && t.network === account.network && t.deviceState === account.deviceState); +} + // const setBalance = (state: State, payload: any): State => { // const newState: Array = [ ...state ]; // let index: number = state.findIndex(t => t.address === payload.address && t.ethAddress === payload.ethAddress); diff --git a/src/js/services/LocalStorageService.js b/src/js/services/LocalStorageService.js index 4823980d..1066c6d8 100644 --- a/src/js/services/LocalStorageService.js +++ b/src/js/services/LocalStorageService.js @@ -13,6 +13,7 @@ import * as SEND from '../actions/constants/send'; import * as WEB3 from '../actions/constants/web3'; import * as PENDING from '../actions/constants/pendingTx'; import { LOCATION_CHANGE } from 'react-router-redux'; +import { findAccountTokens } from '../reducers/TokensReducer'; import type { Middleware, @@ -44,7 +45,7 @@ const findAccounts = (devices: Array, accounts: Array): A const findTokens = (accounts: Array, tokens: Array): Array => { return accounts.reduce((arr, account) => { - return arr.concat(tokens.filter(token => token.ethAddress === account.address && token.network === account.network)); + return arr.concat(findAccountTokens(tokens, account)); }, []); }