1
0
mirror of https://github.com/trezor/trezor-wallet synced 2024-11-24 01:08:27 +00:00

refactor sendForm.token to sendForm.selectedCurrency

This commit is contained in:
Szymon Lesisz 2018-05-10 12:39:49 +02:00
parent efd2d252ed
commit 1007477bae
10 changed files with 97 additions and 90 deletions

View File

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

View File

@ -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) => {
</div>
<div className="content">
<label>Send </label>
<p>{ `${amount} ${ token }` }</p>
<p>{ `${amount} ${ selectedCurrency }` }</p>
<label>To</label>
<p>{ address }</p>
<label>Fee</label>

View File

@ -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) => {
<span className="what-is-it"></span>
</Tooltip>
</label>
<textarea disabled={ network !== token } value={ network !== token ? '' : data } onChange={ event => onDataChange(event.target.value) }></textarea>
<textarea value={ data } onChange={ event => onDataChange(event.target.value) }></textarea>
{/* <textarea disabled={ coinSymbol !== selectedCurrency } value={ coinSymbol !== selectedCurrency ? '' : data } onChange={ event => onDataChange(event.target.value) }></textarea> */}
{ errors.data ? (<span className="error">{ errors.data }</span>) : null }
</div>

View File

@ -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
}
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<Token> = 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 (
<div className="pending-transactions">
<h2>Pending transactions</h2>
{ pendings }
{ pendingTxs }
</div>
)
}

View File

@ -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<string> => {
if (!device || !account || !discovery) return <section></section>;
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<string> => {
amount,
setMax,
coinSymbol,
token,
selectedCurrency,
feeLevels,
selectedFeeLevel,
gasPriceNeedsUpdate,
@ -63,10 +64,10 @@ const _render = (props: Props, state: AccountState): React$Element<string> => {
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<string> => {
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<string> => {
searchable={ false }
clearable= { false }
multi={ false }
value={ token }
disabled={ tokens.length < 2 }
value={ selectedCurrency }
disabled={ tokensSelectData.length < 2 }
onChange={ onCurrencyChange }
options={ tokens } />
options={ tokensSelectData } />
</div>
{ errors.amount ? (<span className="error">{ errors.amount }</span>) : null }
{ warnings.amount ? (<span className="warning">{ warnings.amount }</span>) : null }

View File

@ -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<Props> {
render() {
@ -36,7 +37,7 @@ const _render = (props: Props, state: AccountState): React$Element<string> => {
if (!device || !account) return <section></section>;
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 (

View File

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

View File

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

View File

@ -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<Token>, address: string, symbol: string,
return state.find(t => t.ethAddress === address && t.symbol === symbol && t.deviceState === deviceState);
}
export const findAccountTokens = (state: Array<Token>, account: Account): Array<Token> => {
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<Token> = [ ...state ];
// let index: number = state.findIndex(t => t.address === payload.address && t.ethAddress === payload.ethAddress);

View File

@ -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<TrezorDevice>, accounts: Array<Account>): A
const findTokens = (accounts: Array<Account>, tokens: Array<Token>): Array<Token> => {
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));
}, []);
}