diff --git a/src/components/Transaction/index.js b/src/components/Transaction/index.js new file mode 100644 index 00000000..62660906 --- /dev/null +++ b/src/components/Transaction/index.js @@ -0,0 +1,104 @@ +/* @flow */ +import React from 'react'; +import PropTypes from 'prop-types'; +import styled from 'styled-components'; + +import colors from 'config/colors'; +import Link from 'components/Link'; + +import type { Transaction, Network } from 'flowtype'; + +type Props = { + tx: Transaction, + network: Network, +}; + +const Wrapper = styled.div` + border-bottom: 1px solid ${colors.DIVIDER}; + padding: 14px 0; + display: flex; + flex-direction: row; + + &:last-child { + border-bottom: 0px; + } +`; + +const Addresses = styled.div` + flex: 1; +`; + +const Address = styled.div` + word-break: break-all; + padding: 2px 0px; + &:first-child { + padding-top: 0px; + } + &:last-child { + padding-bottom: 0px; + } +`; + +const Date = styled(Link)` + font-size: 12px; + line-height: 18px; + padding-right: 8px; + border-bottom: 0px; +`; + +const Value = styled.div` + padding-left: 8px; + white-space: nowrap; + text-align: right; + color: ${colors.GREEN_SECONDARY}; + + &.send { + color: ${colors.ERROR_PRIMARY}; + } +`; + +const Amount = styled.div` + border: 1px; +`; + +const Fee = styled.div` + border: 1px; +`; + +const TransactionItem = ({ + tx, + network, +}: Props) => { + const url = `${network.explorer.tx}${tx.hash}`; + const date = typeof tx.timestamp === 'string' && tx.confirmations > 0 ? tx.timestamp : undefined; // TODO: format date + const addresses = (tx.type === 'send' ? tx.outputs : tx.inputs).reduce((arr, item) => arr.concat(item.addresses), []); + + const currency = tx.currency || tx.network; + const isToken = currency !== tx.network; + const amount = isToken ? `${tx.amount} ${currency}` : `${tx.total} ${network.symbol}`; + const fee = isToken && tx.type === 'send' ? `${tx.fee} ${network.symbol}` : undefined; + const operation = tx.type === 'send' ? '-' : '+'; + + return ( + + { date && ({ date })} + + { addresses.map(addr => (
{addr}
)) } + { tx.confirmations <= 0 && ( + Transaction hash: {tx.hash} + )} +
+ + {operation}{amount} + { fee && ({operation}{fee}) } + +
+ ); +}; + +TransactionItem.propTypes = { + tx: PropTypes.object.isRequired, + network: PropTypes.object.isRequired, +}; + +export default TransactionItem; \ No newline at end of file diff --git a/src/views/Wallet/views/Account/Send/components/PendingTransactions/index.js b/src/views/Wallet/views/Account/Send/components/PendingTransactions/index.js index b8c855ae..8b398fcf 100644 --- a/src/views/Wallet/views/Account/Send/components/PendingTransactions/index.js +++ b/src/views/Wallet/views/Account/Send/components/PendingTransactions/index.js @@ -1,19 +1,17 @@ /* @flow */ -import React, { PureComponent } from 'react'; +import React from 'react'; import styled from 'styled-components'; import colors from 'config/colors'; -import ColorHash from 'color-hash'; import { H2 } from 'components/Heading'; -import Link from 'components/Link'; -import ScaleText from 'react-scale-text'; +import Transaction from 'components/Transaction'; + import type { Network } from 'reducers/LocalStorageReducer'; -import type { Token } from 'reducers/TokensReducer'; import type { BaseProps } from '../../index'; +import testData from './test.data'; type Props = { pending: $PropertyType<$ElementType, 'pending'>, - tokens: $PropertyType<$ElementType, 'tokens'>, network: Network } @@ -22,153 +20,18 @@ const Wrapper = styled.div` border-top: 1px solid ${colors.DIVIDER}; `; -const StyledLink = styled(Link)` - text-decoration: none; -`; - -const TransactionWrapper = styled.div` - border-bottom: 1px solid ${colors.DIVIDER}; - padding: 14px 0; - display: flex; - flex-direction: row; - align-items: center; - - &:last-child { - border-bottom: 0px; - } -`; - -const TransactionIcon = styled.div` - padding: 6px; - margin-right: 10px; - width: 36px; - height: 36px; - border-radius: 50%; - line-height: 25px; - text-transform: uppercase; - user-select: none; - text-align: center; - color: ${props => props.textColor}; - background: ${props => props.background}; - border-color: ${props => props.borderColor}; - - &:before { - content: ${props => props.color}; - } -`; - -const P = styled.p``; - -const TransactionName = styled.div` - flex: 1; -`; - -const TransactionAmount = styled.div` - color: colors.TEXT_SECONDARY; -`; - -class PendingTransactions extends PureComponent { - getPendingTransactions() { - return this.props.pending.filter(tx => !tx.rejected); - } - - getTransactionIconColors(tx: any) { - let iconColors = { - textColor: '#fff', - background: '#000', - borderColor: '#000', - }; - const bgColorFactory = new ColorHash({ lightness: 0.7 }); - const textColorFactory = new ColorHash(); - - const isSmartContractTx = tx.currency !== this.props.network.symbol; - - if (isSmartContractTx) { - const token: ?Token = this.findTransactionToken(tx.currency); - - if (!token) { - iconColors = { - textColor: '#ffffff', - background: '#000000', - borderColor: '#000000', - }; - } else { - const bgColor: string = bgColorFactory.hex(token.name); - iconColors = { - textColor: textColorFactory.hex(token.name), - background: bgColor, - borderColor: bgColor, - }; - } - } else { - iconColors = { - textColor: textColorFactory.hex(tx.network), - background: bgColorFactory.hex(tx.network), - borderColor: bgColorFactory.hex(tx.network), - }; - } - return iconColors; - } - - getTransactionSymbol(tx: any) { - let { symbol } = this.props.network; - const isSmartContractTx = tx.currency !== this.props.network.symbol; - if (isSmartContractTx) { - const token: ?Token = this.findTransactionToken(tx.currency); - symbol = token ? token.symbol.toUpperCase() : 'Unknown'; - } - return symbol; - } - - getTransactionName(tx: any) { - let { name } = this.props.network; - const isSmartContractTx = tx.currency !== this.props.network.symbol; - if (isSmartContractTx) { - const token: ?Token = this.findTransactionToken(tx.currency); - name = token ? token.symbol.toUpperCase() : 'Unknown'; - } - return name; - } - - findTransactionToken(transactionCurrency: string) { - return this.props.tokens.find(t => t.symbol === transactionCurrency); - } - - render() { - return ( - -

Pending transactions

- {this.getPendingTransactions().map(tx => ( - - this.getTransactionIconColors(tx).textColor} - background={() => this.getTransactionIconColors(tx).background} - borderColor={() => this.getTransactionIconColors(tx).borderColor} - > - -

{this.getTransactionSymbol(tx)}

-
-
- - - - {this.getTransactionName(tx)} - - - - - {tx.currency !== this.props.network.symbol ? tx.amount : tx.total} {this.getTransactionSymbol(tx)} - -
- ))} -
- ); - } -} +const PendingTransactions = (props: Props) => { + // const pending = props.pending.filter(tx => !tx.rejected).concat(testData); + const pending = props.pending.filter(tx => !tx.rejected); + + return ( + +

Pending transactions

+ {pending.map(tx => ( + + ))} +
+ ); +}; export default PendingTransactions; diff --git a/src/views/Wallet/views/Account/Send/components/PendingTransactions/test.data.js b/src/views/Wallet/views/Account/Send/components/PendingTransactions/test.data.js new file mode 100644 index 00000000..3e78fd5a --- /dev/null +++ b/src/views/Wallet/views/Account/Send/components/PendingTransactions/test.data.js @@ -0,0 +1,99 @@ +export default [ + { + type: 'recv', + timestamp: '16:20', + address: 'a', + deviceState: 'a', + status: 'pending', + confirmations: 0, + inputs: [ + { + addresses: ['in1'], + }, + { + addresses: ['in2'], + }, + ], + outputs: [ + { + addresses: ['out1', 'out2'], + }, + ], + sequence: 1, + hash: '1234', + network: 'eth', + currency: 'eth', + amount: '0.001', + total: '0.001001', + fee: '0.000001', + }, + + { + type: 'send', + address: 'a', + deviceState: 'a', + confirmations: 0, + status: 'pending', + inputs: [ + { + addresses: ['in1', 'in2'], + }, + ], + outputs: [ + { + addresses: ['out1'], + }, + ], + sequence: 1, + hash: '12345', + network: 'eth', + currency: 'T01', + amount: '0.001', + total: '0.001001', + fee: '0.000001', + }, + + { + address: '0x73d0385F4d8E00C5e6504C6030F47BF6212736A8', + amount: '1', + confirmations: 0, + currency: 'T01', + deviceState: '4058d01c7c964787b7d06f0f32ce229088e123a042bf95aad658f1b1b99c73fc', + fee: '0.0002', + hash: '0xbf6ac83bdf29abacbca91cd4100ddd5cd8de16e72911ea7d1daec17ccbfc6099', + inputs: [{ + addresses: ['0x73d0385F4d8E00C5e6504C6030F47BF6212736A8'], + }], + network: 'trop', + outputs: [{ + addresses: ['0xFA01a39f8Abaeb660c3137f14A310d0b414b2A15'], + }], + sequence: 249, + status: 'pending', + timestamp: '', + total: '0.0002', + type: 'send', + }, + + { + address: '0x73d0385F4d8E00C5e6504C6030F47BF6212736A8', + amount: '1', + confirmations: 0, + currency: 'trop', + deviceState: '4058d01c7c964787b7d06f0f32ce229088e123a042bf95aad658f1b1b99c73fc', + fee: '0.0002', + hash: '0xbf6ac83bdf29abacbca91cd4100ddd5cd8de16e72911ea7d1daec17ccbfc6099', + inputs: [{ + addresses: ['0x73d0385F4d8E00C5e6504C6030F47BF6212736A8'], + }], + network: 'trop', + outputs: [{ + addresses: ['0xFA01a39f8Abaeb660c3137f14A310d0b414b2A15'], + }], + sequence: 249, + status: 'pending', + timestamp: '', + total: '0.0002', + type: 'send', + }, +]; \ No newline at end of file