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 (
Copied
{address}
{address && ( {address.slice(0, prefixLength)} {address.slice( prefixLength, prefixLength + trimAmount, )} {address.slice(prefixLength + trimAmount, address_trim)} {address.slice(-trimAmount)} )}
); }; 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
,
Create eToken
,

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
,
Create eToken
,

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
,
Create eToken
,
identicon of tokenId bd1acc4c986de57af8d6d2a64aecad8c30ee80f37ae9d066d758923732ddc9ba
6.001 TBS
, ] `; exports[`Wallet without BCH balance 1`] = ` Array [
You need some XEC in your wallet to create tokens.
,
0 XEC
,
Create eToken
,

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
,
Create eToken
,

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 !== '' ? ( {`identicon } /> ) : ( {`identicon )} {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 !== '' ? ( {`identicon } /> ) : ( {`identicon )} {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
,
Copied
ecash:qzagy47mvh6qxkvcn3acjnz73rkhkc6y7ccxkrr6zd
ecash: qzagy47m vh6qxkvcn3acjnz73rkhkc6y7c cxkrr6zd
,
XEC
eToken
, ] `; 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
,
Copied
ecash:qzagy47mvh6qxkvcn3acjnz73rkhkc6y7ccxkrr6zd
ecash: qzagy47m vh6qxkvcn3acjnz73rkhkc6y7c cxkrr6zd
,
XEC
eToken
, ] `; exports[`Wallet with BCH balances and tokens and state field 1`] = ` Array [
0.06 XEC
,
$ NaN USD
,
Copied
ecash:qzagy47mvh6qxkvcn3acjnz73rkhkc6y7ccxkrr6zd
ecash: qzagy47m vh6qxkvcn3acjnz73rkhkc6y7c cxkrr6zd
,
XEC
eToken
, ] `; 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
,
Copied
ecash:qzagy47mvh6qxkvcn3acjnz73rkhkc6y7ccxkrr6zd
ecash: qzagy47m vh6qxkvcn3acjnz73rkhkc6y7c cxkrr6zd
,
XEC
eToken
, ] `; 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.

, , , ] `;