diff --git a/web/cashtab/src/assets/styles/theme.js b/web/cashtab/src/assets/styles/theme.js
index d6e80894d..8e770cb61 100644
--- a/web/cashtab/src/assets/styles/theme.js
+++ b/web/cashtab/src/assets/styles/theme.js
@@ -1,80 +1,80 @@
export const theme = {
primary: '#00ABE7',
brandSecondary: '#CD0BC3',
contrast: '#fff',
app: {
sidebars: `url("/cashtab_bg.png")`,
background: '#fbfbfd',
},
wallet: {
background: '#fff',
text: {
primary: '#273498',
secondary: '#273498',
},
switch: {
activeCash: {
shadow: 'inset 8px 8px 16px #0074C2, inset -8px -8px 16px #273498',
},
activeToken: {
background: '#CD0BC3',
shadow: 'inset 5px 5px 11px #FF21D0, inset -5px -5px 11px #CD0BC3',
},
inactive: {
background: 'linear-gradient(145deg, #eeeeee, #c8c8c8)',
},
},
borders: { color: '#e2e2e2' },
shadow: 'rgba(0, 0, 0, 1)',
},
tokenListItem: {
background: '#ffffff',
color: '',
boxShadow:
- 'rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px,rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px',
+ 'rgb(136 172 243 / 25%) 0px 10px 30px,rgb(0 0 0 / 3%) 0px 1px 1px, rgb(0 51 167 / 10%) 0px 10px 20px',
border: '#e9eaed',
hoverBorder: '#231F20',
},
footer: {
background: '#fff',
navIconInactive: '#949494',
},
forms: {
error: '#FF21D0',
border: '#e7edf3',
text: '#001137',
addonBackground: '#f4f4f4',
addonForeground: '#3e3f42',
selectionBackground: '#fff',
},
icons: { outlined: '#273498' },
modals: {
buttons: { background: '#fff' },
},
settings: { delete: '#CD0BC3' },
qr: {
copyBorderCash: '#00ABE7',
copyBorderToken: '#FF21D0',
background: '#fff',
token: '#231F20',
- shadow: 'rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px',
+ shadow: 'rgb(136 172 243 / 25%) 0px 10px 30px, rgb(0 0 0 / 3%) 0px 1px 1px, rgb(0 51 167 / 10%) 0px 10px 20px',
},
buttons: {
primary: {
backgroundImage:
'linear-gradient(270deg, #0074C2 0%, #273498 100%)',
color: '#fff',
hoverShadow: '0px 3px 10px -5px rgba(0, 0, 0, 0.75)',
},
secondary: {
background: '#e9eaed',
color: '#444',
hoverShadow: '0px 3px 10px -5px rgba(0, 0, 0, 0.75)',
},
},
collapses: {
background: '#fbfcfd',
border: '#eaedf3',
color: '#3e3f42',
},
};
diff --git a/web/cashtab/src/components/App.js b/web/cashtab/src/components/App.js
index 323e369dc..34658aa22 100644
--- a/web/cashtab/src/components/App.js
+++ b/web/cashtab/src/components/App.js
@@ -1,381 +1,381 @@
import React, { useState, useEffect } from 'react';
import 'antd/dist/antd.less';
import { Modal, Spin } from 'antd';
import { CashLoadingIcon } from '@components/Common/CustomIcons';
import '../index.css';
import styled, { ThemeProvider, createGlobalStyle } from 'styled-components';
import { theme } from '@assets/styles/theme';
import {
FolderOpenFilled,
CaretRightOutlined,
SettingFilled,
AppstoreAddOutlined,
} from '@ant-design/icons';
import Wallet from '@components/Wallet/Wallet';
import Tokens from '@components/Tokens/Tokens';
import Send from '@components/Send/Send';
import SendToken from '@components/Send/SendToken';
import Configure from '@components/Configure/Configure';
import NotFound from '@components/NotFound';
import CashTab from '@assets/cashtab_xec.png';
import './App.css';
import { WalletContext } from '@utils/context';
import { isValidStoredWallet } from '@utils/cashMethods';
import WalletLabel from '@components/Common/WalletLabel.js';
import {
Route,
Redirect,
Switch,
useLocation,
useHistory,
} from 'react-router-dom';
// Easter egg imports not used in extension/src/components/App.js
import TabCash from '@assets/tabcash.png';
import ABC from '@assets/logo_topright.png';
import { checkForTokenById } from '@utils/tokenMethods.js';
import { currency } from './Common/Ticker';
const GlobalStyle = createGlobalStyle`
.ant-modal-wrap > div > div.ant-modal-content > div > div > div.ant-modal-confirm-btns > button, .ant-modal > button, .ant-modal-confirm-btns > button, .ant-modal-footer > button {
border-radius: 8px;
background-color: ${props => props.theme.modals.buttons.background};
color: ${props => props.theme.wallet.text.secondary};
font-weight: bold;
}
.ant-modal-wrap > div > div.ant-modal-content > div > div > div.ant-modal-confirm-btns > button:hover,.ant-modal-confirm-btns > button:hover, .ant-modal-footer > button:hover {
color: ${props => props.theme.primary};
transition: color 0.3s;
background-color: ${props => props.theme.modals.buttons.background};
}
.selectedCurrencyOption {
text-align: left;
color: ${props => props.theme.wallet.text.secondary} !important;
background-color: ${props => props.theme.contrast} !important;
}
.cashLoadingIcon {
color: ${props => props.theme.primary} !important;
font-size: 48px !important;
}
.selectedCurrencyOption:hover {
color: ${props => props.theme.contrast} !important;
background-color: ${props => props.theme.primary} !important;
}
#addrSwitch {
.ant-switch-checked {
background-color: white !important;
}
}
#addrSwitch.ant-switch-checked {
background-image: ${props =>
props.theme.buttons.primary.backgroundImage} !important;
}
`;
const CustomApp = styled.div`
text-align: center;
font-family: 'Gilroy', sans-serif;
background-color: ${props => props.theme.app.background};
`;
const Footer = styled.div`
z-index: 2;
background-color: ${props => props.theme.footer.background};
- border-radius: 20px;
+ border-radius: 20px 20px 0 0;
position: fixed;
bottom: 0;
width: 500px;
+ box-shadow: rgb(136 172 243 / 25%) 0px 10px 30px,
+ rgb(0 0 0 / 3%) 0px 1px 1px, rgb(0 51 167 / 10%) 0px 10px 20px;
@media (max-width: 768px) {
width: 100%;
}
- border-top: 1px solid ${props => props.theme.wallet.borders.color};
`;
export const NavButton = styled.button`
:focus,
:active {
outline: none;
}
cursor: pointer;
padding: 24px 12px 12px 12px;
margin: 0 28px;
@media (max-width: 475px) {
margin: 0 20px;
}
@media (max-width: 420px) {
margin: 0 12px;
}
@media (max-width: 350px) {
margin: 0 8px;
}
background-color: ${props => props.theme.footer.background};
border: none;
font-size: 10.5px;
font-weight: bold;
.anticon {
display: block;
color: ${props => props.theme.footer.navIconInactive};
font-size: 24px;
margin-bottom: 6px;
}
${({ active, ...props }) =>
active &&
`
color: ${props.theme.primary};
.anticon {
color: ${props.theme.primary};
}
`}
`;
export const WalletBody = styled.div`
display: flex;
align-items: center;
justify-content: center;
width: 100%;
min-height: 100vh;
background-image: ${props => props.theme.app.sidebars};
background-attachment: fixed;
`;
export const WalletCtn = styled.div`
position: relative;
width: 500px;
background-color: ${props => props.theme.footerBackground};
min-height: 100vh;
padding: 10px 30px 120px 30px;
background: ${props => props.theme.wallet.background};
-webkit-box-shadow: 0px 0px 24px 1px ${props => props.theme.wallet.shadow};
-moz-box-shadow: 0px 0px 24px 1px ${props => props.theme.wallet.shadow};
box-shadow: 0px 0px 24px 1px ${props => props.theme.wallet.shadow};
@media (max-width: 768px) {
width: 100%;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
}
`;
export const HeaderCtn = styled.div`
display: flex;
align-items: center;
justify-content: center;
width: 100%;
padding: 20px 0 30px;
margin-bottom: 20px;
justify-content: space-between;
- border-bottom: 1px solid ${props => props.theme.wallet.borders.color};
a {
color: ${props => props.theme.wallet.text.secondary};
:hover {
color: ${props => props.theme.primary};
}
}
@media (max-width: 768px) {
a {
font-size: 12px;
}
padding: 10px 0 20px;
}
`;
export const CashTabLogo = styled.img`
width: 120px;
@media (max-width: 768px) {
width: 110px;
}
`;
// AbcLogo styled component not included in extension, replaced by open in new tab link
export const AbcLogo = styled.img`
width: 150px;
@media (max-width: 768px) {
width: 120px;
}
`;
// Easter egg styled component not used in extension/src/components/App.js
export const EasterEgg = styled.img`
position: fixed;
bottom: -195px;
margin: 0;
right: 10%;
transition-property: bottom;
transition-duration: 1.5s;
transition-timing-function: ease-out;
:hover {
bottom: 0;
}
@media screen and (max-width: 1250px) {
display: none;
}
`;
const App = () => {
const ContextValue = React.useContext(WalletContext);
const { wallet, loading } = ContextValue;
const [loadingUtxosAfterSend, setLoadingUtxosAfterSend] = useState(false);
// If wallet is unmigrated, do not show page until it has migrated
// An invalid wallet will be validated/populated after the next API call, ETA 10s
const validWallet = isValidStoredWallet(wallet);
const location = useLocation();
const history = useHistory();
const selectedKey =
location && location.pathname ? location.pathname.substr(1) : '';
// Easter egg boolean not used in extension/src/components/App.js
const hasTab = validWallet
? checkForTokenById(
wallet.state.tokens,
'50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e',
)
: false;
useEffect(() => {
// If URL is not as specified in currency.appURL in Ticker.js, show a popup
const currentUrl = window.location.hostname;
if (currentUrl !== currency.appUrl) {
console.log(
`Loaded URL ${currentUrl} does not match app URL ${currency.appUrl}!`,
);
Modal.warning({
title: 'Cashtab is moving!',
content: (
Cashtab is moving to a new home at{' '}
Cashtab.com
Please write down your wallet 12-word seed and
import it at the new domain.
At the end of the month, cashtabapp.com will
auto-fwd to cashtab.com after one minute.
),
});
}
}, []);
return (
{/*Begin component not included in extension as desktop only*/}
{hasTab && (
)}
{/*End component not included in extension as desktop only*/}
{/*Begin component not included in extension as replaced by open in tab link*/}
{/*Begin component not included in extension as replaced by open in tab link*/}
(
)}
/>
{wallet ? (
) : null}
);
};
export default App;
diff --git a/web/cashtab/src/components/Common/QRCode.js b/web/cashtab/src/components/Common/QRCode.js
index 712a1391c..72574bb0e 100644
--- a/web/cashtab/src/components/Common/QRCode.js
+++ b/web/cashtab/src/components/Common/QRCode.js
@@ -1,261 +1,260 @@
import React, { useState } from 'react';
import styled from 'styled-components';
import RawQRCode from 'qrcode.react';
import {
currency,
isValidCashPrefix,
isValidTokenPrefix,
} from '@components/Common/Ticker.js';
import { CopyToClipboard } from 'react-copy-to-clipboard';
import { Event } from '@utils/GoogleAnalytics';
import { convertToEcashPrefix } from '@utils/cashMethods';
export const StyledRawQRCode = styled(RawQRCode)`
cursor: pointer;
- border-radius: 23px;
+ border-radius: 26px;
background: ${props => props.theme.qr.background};
box-shadow: ${props => props.theme.qr.shadow};
margin-bottom: 10px;
- border: 1px solid ${props => props.theme.wallet.borders.color};
path:first-child {
fill: ${props => props.theme.qr.background};
}
:hover {
border-color: ${({ xec = 0, ...props }) =>
xec === 1 ? props.theme.primary : props.theme.qr.token};
}
@media (max-width: 768px) {
border-radius: 18px;
width: 170px;
height: 170px;
}
`;
const Copied = styled.div`
font-size: 18px;
font-weight: bold;
width: 100%;
text-align: center;
background-color: ${({ xec = 0, ...props }) =>
xec === 1 ? props.theme.primary : props.theme.qr.token};
border: 1px solid;
border-color: ${({ xec = 0, ...props }) =>
xec === 1
? props.theme.qr.copyBorderCash
: props.theme.qr.copyBorderToken};
color: ${props => props.theme.contrast};
position: absolute;
top: 65px;
padding: 30px 0;
@media (max-width: 768px) {
top: 52px;
padding: 20px 0;
}
`;
const PrefixLabel = styled.span`
text-align: right;
font-size: 14px;
font-weight: bold;
@media (max-width: 768px) {
font-size: 12px;
}
@media (max-width: 400px) {
font-size: 10px;
}
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
`;
const AddressHighlightTrim = styled.span`
font-weight: bold;
font-size: 14px;
@media (max-width: 768px) {
font-size: 12px;
}
@media (max-width: 400px) {
font-size: 10px;
}
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
`;
const CustomInput = styled.div`
font-size: 12px;
color: ${({ xec = 0, ...props }) =>
xec === 1
? props.theme.wallet.text.secondary
: props.theme.brandSecondary};
text-align: center;
cursor: pointer;
margin-bottom: 0px;
padding: 6px 0;
font-family: 'Roboto Mono', monospace;
border-radius: 5px;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
input {
border: none;
width: 100%;
text-align: center;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
cursor: pointer;
color: ${props => props.theme.wallet.text.primary};
padding: 10px 0;
background: transparent;
margin-bottom: 15px;
display: none;
}
input:focus {
outline: none;
}
input::selection {
background: transparent;
color: ${props => props.theme.wallet.text.primary};
}
@media (max-width: 768px) {
font-size: 10px;
input {
font-size: 10px;
margin-bottom: 10px;
}
}
@media (max-width: 400px) {
font-size: 7px;
input {
font-size: 10px;
margin-bottom: 10px;
}
}
`;
export const QRCode = ({
address,
size = 210,
onClick = () => null,
...otherProps
}) => {
address = address ? convertToEcashPrefix(address) : '';
const [visible, setVisible] = useState(false);
const trimAmount = 8;
const address_trim = address ? address.length - trimAmount : '';
const addressSplit = address ? address.split(':') : [''];
const addressPrefix = addressSplit[0];
const prefixLength = addressPrefix.length + 1;
const isCash = isValidCashPrefix(address);
const txtRef = React.useRef(null);
const handleOnClick = evt => {
setVisible(true);
setTimeout(() => {
setVisible(false);
}, 1500);
onClick(evt);
};
const handleOnCopy = () => {
// Event.("Category", "Action", "Label")
// xec or etoken?
let eventLabel = currency.ticker;
if (address) {
const isToken = isValidTokenPrefix(address);
if (isToken) {
eventLabel = currency.tokenTicker;
}
// Event('Category', 'Action', 'Label')
Event('Wallet', 'Copy Address', eventLabel);
}
setVisible(true);
setTimeout(() => {
txtRef.current.select();
}, 100);
};
return (
);
};
diff --git a/web/cashtab/src/components/Tokens/__tests__/__snapshots__/Tokens.test.js.snap b/web/cashtab/src/components/Tokens/__tests__/__snapshots__/Tokens.test.js.snap
index 0c052c07e..9cc281c22 100644
--- a/web/cashtab/src/components/Tokens/__tests__/__snapshots__/Tokens.test.js.snap
+++ b/web/cashtab/src/components/Tokens/__tests__/__snapshots__/Tokens.test.js.snap
@@ -1,419 +1,419 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP @generated
exports[`Wallet with BCH balances 1`] = `
Array [
You need some
XEC
in your wallet to create tokens.
,
0
XEC
,
,
You need at least
5.5
XEC
(
$
NaN
USD
) to create a token
,
"No ",
"eToken",
" tokens in this wallet",
]
`;
exports[`Wallet with BCH balances and tokens 1`] = `
Array [
You need some
XEC
in your wallet to create tokens.
,
0
XEC
,
,
You need at least
5.5
XEC
(
$
NaN
USD
) to create a token
,
"No ",
"eToken",
" tokens in this wallet",
]
`;
exports[`Wallet with BCH balances and tokens and state field 1`] = `
Array [
0.06
XEC
,
$
NaN
USD
,
,
,
]
`;
exports[`Wallet without BCH balance 1`] = `
Array [
You need some
XEC
in your wallet to create tokens.
,
0
XEC
,
,
You need at least
5.5
XEC
(
$
NaN
USD
) to create a token
,
"No ",
"eToken",
" tokens in this wallet",
]
`;
exports[`Without wallet defined 1`] = `
Array [
You need some
XEC
in your wallet to create tokens.
,
0
XEC
,
,
You need at least
5.5
XEC
(
$
NaN
USD
) to create a token
,
"No ",
"eToken",
" tokens in this wallet",
]
`;
diff --git a/web/cashtab/src/components/Wallet/TokenListItem.js b/web/cashtab/src/components/Wallet/TokenListItem.js
index ccdb0003b..c90486563 100644
--- a/web/cashtab/src/components/Wallet/TokenListItem.js
+++ b/web/cashtab/src/components/Wallet/TokenListItem.js
@@ -1,81 +1,84 @@
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import makeBlockie from 'ethereum-blockies-base64';
import { Img } from 'react-image';
import { currency } from '@components/Common/Ticker';
const TokenIcon = styled.div`
height: 32px;
width: 32px;
`;
const BalanceAndTicker = styled.div`
font-size: 1rem;
`;
const Wrapper = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 25px;
- border-radius: 3px;
+ border-radius: 16px;
background: ${props => props.theme.tokenListItem.background};
- margin-bottom: 3px;
+ margin-bottom: 10px;
box-shadow: ${props => props.theme.tokenListItem.boxShadow};
border: 1px solid ${props => props.theme.tokenListItem.border};
:hover {
- border-color: ${props => props.theme.tokenListItem.hoverBorder};
+ transform: translateY(-2px);
+ box-shadow: rgb(136 172 243 / 25%) 0px 10px 30px,
+ rgb(0 0 0 / 3%) 0px 1px 1px, rgb(0 51 167 / 10%) 0px 10px 20px;
+ transition: all 0.8s cubic-bezier(0.075, 0.82, 0.165, 1) 0s;
}
`;
const TokenListItem = ({ ticker, balance, tokenId }) => {
return (
{currency.tokenIconsUrl !== '' ? (
}
/>
) : (
)}
{balance} {ticker}
);
};
TokenListItem.propTypes = {
ticker: PropTypes.string,
balance: PropTypes.string,
tokenId: PropTypes.string,
};
export default TokenListItem;
diff --git a/web/cashtab/src/components/Wallet/Tx.js b/web/cashtab/src/components/Wallet/Tx.js
index 37077ce7c..125ec87c8 100644
--- a/web/cashtab/src/components/Wallet/Tx.js
+++ b/web/cashtab/src/components/Wallet/Tx.js
@@ -1,379 +1,381 @@
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import {
ArrowUpOutlined,
ArrowDownOutlined,
ExperimentOutlined,
ExclamationOutlined,
} from '@ant-design/icons';
import { currency } from '@components/Common/Ticker';
import makeBlockie from 'ethereum-blockies-base64';
import { Img } from 'react-image';
import { formatBalance, fromLegacyDecimals } from '@utils/cashMethods';
const SentTx = styled(ArrowUpOutlined)`
color: ${props => props.theme.secondary} !important;
`;
const ReceivedTx = styled(ArrowDownOutlined)`
color: ${props => props.theme.primary} !important;
`;
const GenesisTx = styled(ExperimentOutlined)`
color: ${props => props.theme.primary} !important;
`;
const UnparsedTx = styled(ExclamationOutlined)`
color: ${props => props.theme.primary} !important;
`;
const DateType = styled.div`
text-align: left;
padding: 12px;
@media screen and (max-width: 500px) {
font-size: 0.8rem;
}
`;
const SentLabel = styled.span`
font-weight: bold;
color: ${props => props.theme.secondary} !important;
`;
const ReceivedLabel = styled.span`
font-weight: bold;
color: ${props => props.theme.primary} !important;
`;
const TxIcon = styled.div`
svg {
width: 32px;
height: 32px;
}
height: 32px;
width: 32px;
@media screen and (max-width: 500px) {
svg {
width: 24px;
height: 24px;
}
height: 24px;
width: 24px;
}
`;
const TxInfo = styled.div`
padding: 12px;
font-size: 1rem;
text-align: right;
color: ${props =>
props.outgoing ? props.theme.secondary : props.theme.primary};
@media screen and (max-width: 500px) {
font-size: 0.8rem;
}
`;
const TxFiatPrice = styled.span`
font-size: 0.8rem;
`;
const TokenInfo = styled.div`
display: grid;
grid-template-rows: 50%;
grid-template-columns: 24px auto;
padding: 12px;
font-size: 1rem;
color: ${props =>
props.outgoing ? props.theme.secondary : props.theme.primary};
@media screen and (max-width: 500px) {
font-size: 0.8rem;
grid-template-columns: 16px auto;
}
`;
const TxTokenIcon = styled.div`
img {
height: 24px;
width: 24px;
}
@media screen and (max-width: 500px) {
img {
height: 16px;
width: 16px;
}
}
grid-column-start: 1;
grid-column-end: span 1;
grid-row-start: 1;
grid-row-end: span 2;
align-self: center;
`;
const TokenTxAmt = styled.div`
padding-left: 12px;
text-align: right;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
`;
const TokenName = styled.div`
padding-left: 12px;
font-size: 0.8rem;
@media screen and (max-width: 500px) {
font-size: 0.6rem;
}
text-align: right;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
`;
const TxWrapper = styled.div`
display: grid;
grid-template-columns: 36px 30% 50%;
justify-content: space-between;
align-items: center;
padding: 15px 25px;
- border-radius: 3px;
+ border-radius: 16px;
background: ${props => props.theme.tokenListItem.background};
- margin-bottom: 3px;
+ margin-bottom: 12px;
box-shadow: ${props => props.theme.tokenListItem.boxShadow};
- border: 1px solid ${props => props.theme.tokenListItem.border};
:hover {
- border-color: ${props => props.theme.primary};
+ transform: translateY(-2px);
+ box-shadow: rgb(136 172 243 / 25%) 0px 10px 30px,
+ rgb(0 0 0 / 3%) 0px 1px 1px, rgb(0 51 167 / 10%) 0px 10px 20px;
+ transition: all 0.8s cubic-bezier(0.075, 0.82, 0.165, 1) 0s;
}
@media screen and (max-width: 500px) {
grid-template-columns: 24px 30% 50%;
padding: 12px 12px;
}
`;
const Tx = ({ data, fiatPrice, fiatCurrency }) => {
const txDate =
typeof data.blocktime === 'undefined'
? new Date().toLocaleDateString()
: new Date(data.blocktime * 1000).toLocaleDateString();
// if data only includes height and txid, then the tx could not be parsed by cashtab
// render as such but keep link to block explorer
let unparsedTx = false;
if (!Object.keys(data).includes('outgoingTx')) {
unparsedTx = true;
}
return (
<>
{unparsedTx ? (
Unparsed
{txDate}
Open in Explorer
) : (
{data.outgoingTx ? (
<>
{data.tokenTx &&
data.tokenInfo.transactionType === 'GENESIS' ? (
) : (
)}
>
) : (
)}
{data.outgoingTx ? (
<>
{data.tokenTx &&
data.tokenInfo.transactionType === 'GENESIS' ? (
Genesis
) : (
Sent
)}
>
) : (
Received
)}
{txDate}
{data.tokenTx ? (
{data.tokenTx && data.tokenInfo ? (
<>
{currency.tokenIconsUrl !== '' ? (
}
/>
) : (
)}
{data.outgoingTx ? (
<>
{data.tokenInfo.transactionType ===
'GENESIS' ? (
<>
+{' '}
{data.tokenInfo.qtyReceived.toString()}
{
data.tokenInfo
.tokenTicker
}
{
data.tokenInfo
.tokenName
}
>
) : (
<>
-{' '}
{data.tokenInfo.qtySent.toString()}
{
data.tokenInfo
.tokenTicker
}
{
data.tokenInfo
.tokenName
}
>
)}
>
) : (
<>
+{' '}
{data.tokenInfo.qtyReceived.toString()}
{data.tokenInfo.tokenTicker}
{data.tokenInfo.tokenName}
>
)}
>
) : (
Token Tx
)}
) : (
<>
{data.outgoingTx ? (
<>
-{' '}
{formatBalance(
fromLegacyDecimals(data.amountSent),
)}{' '}
{currency.ticker}
{fiatPrice !== null &&
!isNaN(data.amountSent) && (
-{' '}
{
currency.fiatCurrencies[
fiatCurrency
].symbol
}
{(
fromLegacyDecimals(
data.amountSent,
) * fiatPrice
).toFixed(2)}{' '}
{
currency.fiatCurrencies
.fiatCurrency
}
)}
>
) : (
<>
+{' '}
{formatBalance(
fromLegacyDecimals(
data.amountReceived,
),
)}{' '}
{currency.ticker}
{fiatPrice !== null &&
!isNaN(data.amountReceived) && (
+{' '}
{
currency.fiatCurrencies[
fiatCurrency
].symbol
}
{(
fromLegacyDecimals(
data.amountReceived,
) * fiatPrice
).toFixed(2)}{' '}
{
currency.fiatCurrencies
.fiatCurrency
}
)}
>
)}
>
)}
)}
>
);
};
Tx.propTypes = {
data: PropTypes.object,
fiatPrice: PropTypes.number,
fiatCurrency: PropTypes.string,
};
export default Tx;
diff --git a/web/cashtab/src/components/Wallet/__tests__/__snapshots__/Wallet.test.js.snap b/web/cashtab/src/components/Wallet/__tests__/__snapshots__/Wallet.test.js.snap
index 22720619c..545d75c60 100644
--- a/web/cashtab/src/components/Wallet/__tests__/__snapshots__/Wallet.test.js.snap
+++ b/web/cashtab/src/components/Wallet/__tests__/__snapshots__/Wallet.test.js.snap
@@ -1,622 +1,622 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP @generated
exports[`Wallet with BCH balances 1`] = `
Array [
🎉
Congratulations on your new wallet!
🎉
Start using the wallet immediately to receive
XEC
payments, or load it up with
XEC
to send to others
,
0
XEC
,
,
,
]
`;
exports[`Wallet with BCH balances and tokens 1`] = `
Array [
🎉
Congratulations on your new wallet!
🎉
Start using the wallet immediately to receive
XEC
payments, or load it up with
XEC
to send to others
,
0
XEC
,
,
,
]
`;
exports[`Wallet with BCH balances and tokens and state field 1`] = `
Array [
0.06
XEC
,
$
NaN
USD
,
,
,
]
`;
exports[`Wallet without BCH balance 1`] = `
Array [
🎉
Congratulations on your new wallet!
🎉
Start using the wallet immediately to receive
XEC
payments, or load it up with
XEC
to send to others
,
0
XEC
,
,
,
]
`;
exports[`Without wallet defined 1`] = `
Array [
Welcome to Cashtab!
,
Cashtab is an
open source,
non-custodial web wallet for
eCash
.
Want to learn more?
Check out the Cashtab documentation.
,
,
,
]
`;