diff --git a/web/cashtab/src/assets/copy.svg b/web/cashtab/src/assets/copy.svg new file mode 100644 index 000000000..37b371f6a --- /dev/null +++ b/web/cashtab/src/assets/copy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/cashtab/src/assets/external-link-square-alt.svg b/web/cashtab/src/assets/external-link-square-alt.svg new file mode 100644 index 000000000..e2b6e07ee --- /dev/null +++ b/web/cashtab/src/assets/external-link-square-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/cashtab/src/components/Common/CustomIcons.js b/web/cashtab/src/components/Common/CustomIcons.js index c487f449f..185623392 100644 --- a/web/cashtab/src/components/Common/CustomIcons.js +++ b/web/cashtab/src/components/Common/CustomIcons.js @@ -1,89 +1,105 @@ import * as React from 'react'; import styled from 'styled-components'; import { CopyOutlined, DollarOutlined, LoadingOutlined, WalletOutlined, QrcodeOutlined, SettingOutlined, LockOutlined, } from '@ant-design/icons'; import { Image } from 'antd'; import { currency } from '@components/Common/Ticker'; import { ReactComponent as Send } from '@assets/send.svg'; import { ReactComponent as Receive } from '@assets/receive.svg'; import { ReactComponent as Genesis } from '@assets/flask.svg'; import { ReactComponent as Unparsed } from '@assets/alert-circle.svg'; import { ReactComponent as Home } from '@assets/home.svg'; import { ReactComponent as Settings } from '@assets/cog.svg'; +import { ReactComponent as CopySolid } from '@assets/copy.svg'; +import { ReactComponent as LinkSolid } from '@assets/external-link-square-alt.svg'; export const CashLoadingIcon = ; export const CashReceivedNotificationIcon = () => ( ); export const TokenReceivedNotificationIcon = () => ( ); export const MessageSignedNotificationIcon = () => ( ); export const ThemedCopyOutlined = styled(CopyOutlined)` color: ${props => props.theme.icons.outlined} !important; `; export const ThemedDollarOutlined = styled(DollarOutlined)` color: ${props => props.theme.icons.outlined} !important; `; export const ThemedWalletOutlined = styled(WalletOutlined)` color: ${props => props.theme.icons.outlined} !important; `; export const ThemedQrcodeOutlined = styled(QrcodeOutlined)` color: ${props => props.theme.walletBackground} !important; `; export const ThemedSettingOutlined = styled(SettingOutlined)` color: ${props => props.theme.icons.outlined} !important; `; export const ThemedLockOutlined = styled(LockOutlined)` color: ${props => props.theme.icons.outlined} !important; `; +export const ThemedCopySolid = styled(CopySolid)` + fill: ${props => props.theme.contrast}; + padding: 0rem 0rem 0.27rem 0rem; + height: 1.3em; + width: 1.3em; +`; + +export const ThemedLinkSolid = styled(LinkSolid)` + fill: ${props => props.theme.contrast}; + padding: 0.15rem 0rem 0.18rem 0rem; + height: 1.3em; + width: 1.3em; +`; + export const LoadingBlock = styled.div` width: 100%; display: flex; align-items: center; justify-content: center; padding: 24px; flex-direction: column; svg { width: 50px; height: 50px; fill: ${props => props.theme.eCashBlue}; } `; export const CashLoader = () => ( ); export const ReceiveIcon = () => ; export const GenesisIcon = () => ; export const UnparsedIcon = () => ; export const HomeIcon = () => ; export const SettingsIcon = () => ; export const SendIcon = styled(Send)` transform: rotate(-35deg); `; diff --git a/web/cashtab/src/components/Common/Notifications.js b/web/cashtab/src/components/Common/Notifications.js index 4b0e7943d..81332534e 100644 --- a/web/cashtab/src/components/Common/Notifications.js +++ b/web/cashtab/src/components/Common/Notifications.js @@ -1,182 +1,192 @@ import * as React from 'react'; import { notification } from 'antd'; import { CashReceivedNotificationIcon, TokenReceivedNotificationIcon, } from '@components/Common/CustomIcons'; import Paragraph from 'antd/lib/typography/Paragraph'; import { currency } from '@components/Common/Ticker'; import { MessageSignedNotificationIcon } from '@components/Common/CustomIcons'; import { isMobile } from 'react-device-detect'; const getDeviceNotificationStyle = () => { if (isMobile) { const notificationStyle = { width: '100%', marginTop: '10%', }; return notificationStyle; } if (!isMobile) { const notificationStyle = { width: '100%', }; return notificationStyle; } }; // Success Notifications: const sendXecNotification = link => { const notificationStyle = getDeviceNotificationStyle(); notification.success({ message: 'Success', description: ( Transaction successful. Click to view in block explorer. ), duration: currency.notificationDurationShort, icon: , style: notificationStyle, }); }; const createTokenNotification = link => { const notificationStyle = getDeviceNotificationStyle(); notification.success({ message: 'Success', description: ( Token created! Click to view in block explorer. ), icon: , style: notificationStyle, }); }; const tokenIconSubmitSuccess = () => { const notificationStyle = getDeviceNotificationStyle(); notification.success({ message: 'Success', description: ( Your eToken icon was successfully submitted. ), icon: , style: notificationStyle, }); }; const sendTokenNotification = link => { const notificationStyle = getDeviceNotificationStyle(); notification.success({ message: 'Success', description: ( Transaction successful. Click to view in block explorer. ), duration: currency.notificationDurationShort, icon: , style: notificationStyle, }); }; const xecReceivedNotification = ( balances, previousBalances, cashtabSettings, fiatPrice, ) => { const notificationStyle = getDeviceNotificationStyle(); notification.success({ message: 'Transaction received', description: ( +{' '} {parseFloat( Number( balances.totalBalance - previousBalances.totalBalance, ).toFixed(currency.cashDecimals), ).toLocaleString()}{' '} {currency.ticker}{' '} {cashtabSettings && cashtabSettings.fiatCurrency && `(${ currency.fiatCurrencies[cashtabSettings.fiatCurrency] .symbol }${( Number( balances.totalBalance - previousBalances.totalBalance, ) * fiatPrice ).toFixed( currency.cashDecimals, )} ${cashtabSettings.fiatCurrency.toUpperCase()})`} ), duration: currency.notificationDurationShort, icon: , style: notificationStyle, }); }; const eTokenReceivedNotification = ( currency, receivedSlpTicker, receivedSlpQty, receivedSlpName, ) => { const notificationStyle = getDeviceNotificationStyle(); notification.success({ message: `${currency.tokenTicker} transaction received: ${receivedSlpTicker}`, description: ( You received {receivedSlpQty.toString()} {receivedSlpName} ), duration: currency.notificationDurationShort, icon: , style: notificationStyle, }); }; // Error Notification: const errorNotification = (error, message, stringDescribingCallEvent) => { const notificationStyle = getDeviceNotificationStyle(); console.log(error, message, stringDescribingCallEvent); notification.error({ message: 'Error', description: message, duration: currency.notificationDurationLong, style: notificationStyle, }); }; const messageSignedNotification = msgSignature => { const notificationStyle = getDeviceNotificationStyle(); notification.success({ message: 'Message Signature Generated', description: {msgSignature}, icon: , style: notificationStyle, }); }; +const generalNotification = (data, msgStr) => { + const notificationStyle = getDeviceNotificationStyle(); + notification.success({ + message: msgStr, + description: data, + style: notificationStyle, + }); +}; + export { sendXecNotification, createTokenNotification, tokenIconSubmitSuccess, sendTokenNotification, xecReceivedNotification, eTokenReceivedNotification, errorNotification, messageSignedNotification, + generalNotification, }; diff --git a/web/cashtab/src/components/Common/StyledCollapse.js b/web/cashtab/src/components/Common/StyledCollapse.js index 782c03f8b..e98eb1be6 100644 --- a/web/cashtab/src/components/Common/StyledCollapse.js +++ b/web/cashtab/src/components/Common/StyledCollapse.js @@ -1,92 +1,114 @@ import styled from 'styled-components'; import { Collapse } from 'antd'; export const StyledCollapse = styled(Collapse)` background: ${props => props.theme.collapses.background} !important; border: 1px solid ${props => props.theme.collapses.border} !important; .ant-collapse-content { border-top: none; background-color: ${props => props.theme.collapses.expandedBackground} !important; } .ant-collapse-item { border-bottom: none !important; } *:not(button) { color: ${props => props.theme.collapses.color} !important; } `; export const TokenCollapse = styled(Collapse)` ${({ disabled = false, ...props }) => disabled === true ? ` background: ${props.theme.buttons.secondary.background} !important; .ant-collapse-header { font-size: 18px; font-weight: bold; color: ${props.theme.buttons.secondary.color} !important; svg { color: ${props.theme.buttons.secondary.color} !important; } } .ant-collapse-arrow { font-size: 18px; } ` : ` background: ${props.theme.eCashBlue} !important; .ant-collapse-header { font-size: 18px; font-weight: bold; color: ${props.theme.contrast} !important; svg { color: ${props.theme.contrast} !important; } } .ant-collapse-arrow { font-size: 18px; } `} `; export const AdvancedCollapse = styled(Collapse)` .ant-collapse-content { background-color: ${props => props.theme.advancedCollapse.expandedBackground} !important; } ${({ disabled = false, ...props }) => disabled === true ? ` background: ${props.theme.buttons.secondary.background} !important; .ant-collapse-header { font-size: 18px; font-weight: normal; color: ${props.theme.buttons.secondary.color} !important; svg { color: ${props.theme.buttons.secondary.color} !important; } } .ant-collapse-arrow { font-size: 18px; } ` : ` background: ${props.theme.advancedCollapse.background} !important; .ant-collapse-header { font-size: 18px; font-weight: bold; color: ${props.theme.advancedCollapse.color} !important; svg { color: ${props.theme.advancedCollapse.icon} !important; } } .ant-collapse-arrow { font-size: 18px; } `} `; + +export const AntdContextCollapseWrapper = styled.div` + .ant-collapse { + border: none !important; + background-color: transparent !important; + } + .ant-collapse-item { + border: none !important; + } + .ant-collapse-header { + padding: 0 !important; + color: ${props => props.theme.forms.text} !important; + } + border-radius: 16px; + .ant-collapse-content-box { + padding-right: 0 !important; + } + + @media screen and (max-width: 500px) { + grid-template-columns: 24px 30% 50%; + } +`; diff --git a/web/cashtab/src/components/Configure/__tests__/__snapshots__/Configure.test.js.snap b/web/cashtab/src/components/Configure/__tests__/__snapshots__/Configure.test.js.snap index f27cbd546..65dd7225c 100644 --- a/web/cashtab/src/components/Configure/__tests__/__snapshots__/Configure.test.js.snap +++ b/web/cashtab/src/components/Configure/__tests__/__snapshots__/Configure.test.js.snap @@ -1,805 +1,805 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP @generated exports[`Configure with a wallet 1`] = `

Backup your wallet

Your seed phrase is the only way to restore your wallet. Write it down. Keep it safe.
Click to reveal seed phrase

Manage Wallets

Fiat Currency

US Dollar ($)

General Settings

Lock App
[ Documentation | ]
`; exports[`Configure without a wallet 1`] = `

Backup your wallet

Your seed phrase is the only way to restore your wallet. Write it down. Keep it safe.

Manage Wallets

Fiat Currency

US Dollar ($)

General Settings

Lock App
[ Documentation | ]
`; diff --git a/web/cashtab/src/components/Home/Tx.js b/web/cashtab/src/components/Home/Tx.js index 94f8de7d9..83617fe68 100644 --- a/web/cashtab/src/components/Home/Tx.js +++ b/web/cashtab/src/components/Home/Tx.js @@ -1,544 +1,707 @@ import React from 'react'; import { Link } from 'react-router-dom'; import PropTypes from 'prop-types'; -import styled from 'styled-components'; +import styled, { css } from 'styled-components'; import { SendIcon, ReceiveIcon, GenesisIcon, UnparsedIcon, } from '@components/Common/CustomIcons'; import { currency } from '@components/Common/Ticker'; import { fromLegacyDecimals } from '@utils/cashMethods'; import { formatBalance, formatDate } from '@utils/formatting'; import TokenIcon from '@components/Tokens/TokenIcon'; - +import { Collapse } from 'antd'; +import { AntdContextCollapseWrapper } from '@components/Common/StyledCollapse'; +import { generalNotification } from '@components/Common/Notifications'; +import { CopyToClipboard } from 'react-copy-to-clipboard'; +import { + ThemedCopySolid, + ThemedLinkSolid, +} from '@components/Common/CustomIcons'; const TxIcon = styled.div` svg { width: 20px; height: 20px; } height: 40px; width: 40px; border: 1px solid #fff; display: flex; align-items: center; justify-content: center; border-radius: 100px; `; const SentTx = styled(TxIcon)` svg { margin-right: -3px; } fill: ${props => props.theme.contrast}; `; const ReceivedTx = styled(TxIcon)` svg { fill: ${props => props.theme.eCashBlue}; } border-color: ${props => props.theme.eCashBlue}; `; const GenesisTx = styled(TxIcon)` border-color: ${props => props.theme.genesisGreen}; svg { fill: ${props => props.theme.genesisGreen}; } `; const UnparsedTx = styled(TxIcon)` color: ${props => props.theme.eCashBlue} !important; `; const DateType = styled.div` text-align: left; padding: 12px; @media screen and (max-width: 500px) { font-size: 0.8rem; } `; const LeftTextCtn = styled.div` text-align: left; display: flex; align-items: left; flex-direction: column; margin-left: 10px; h3 { color: ${props => props.theme.contrast}; font-size: 14px; font-weight: 700; margin: 0; } .genesis { color: ${props => props.theme.genesisGreen}; } .received { color: ${props => props.theme.eCashBlue}; } h4 { font-size: 12px; color: ${props => props.theme.lightWhite}; margin: 0; } `; const RightTextCtn = styled.div` text-align: right; display: flex; align-items: left; flex-direction: column; margin-left: 10px; h3 { color: ${props => props.theme.contrast}; font-size: 14px; font-weight: 700; margin: 0; } .genesis { color: ${props => props.theme.genesisGreen}; } .received { color: ${props => props.theme.eCashBlue}; } h4 { font-size: 12px; color: ${props => props.theme.lightWhite}; margin: 0; } `; const OpReturnType = styled.div` text-align: right; width: 100%; padding: 10px; border-radius: 5px; background: ${props => props.theme.sentMessage}; margin-top: 15px; h4 { color: ${props => props.theme.lightWhite}; margin: 0; font-size: 12px; display: inline-block; } p { color: ${props => props.theme.contrast}; margin: 0; font-size: 14px; margin-bottom: 10px; overflow-wrap: break-word; } a { color: ${props => props.theme.contrast}; margin: 0; font-size: 10px; border: 1px solid ${props => props.theme.contrast}; border-radius: 5px; padding: 2px 10px; opacity: 0.6; } a:hover { opacity: 1; border-color: ${props => props.theme.eCashBlue}; color: ${props => props.theme.contrast}; background: ${props => props.theme.eCashBlue}; } ${({ received, ...props }) => received && ` text-align: left; background: ${props.theme.receivedMessage}; `} `; const SentLabel = styled.span` font-weight: bold; color: ${props => props.theme.secondary} !important; `; const ReceivedLabel = styled.span` font-weight: bold; color: ${props => props.theme.eCashBlue} !important; `; const GenesisLabel = styled.span` font-weight: bold; color: ${props => props.theme.genesisGreen} !important; `; const CashtabMessageLabel = styled.span` text-align: left; font-weight: bold; color: ${props => props.theme.eCashBlue} !important; white-space: nowrap; `; const EncryptionMessageLabel = styled.span` font-weight: bold; font-size: 12px; color: ${props => props.theme.encryptionRed}; white-space: nowrap; `; const UnauthorizedDecryptionMessage = styled.span` text-align: left; color: ${props => props.theme.encryptionRed}; white-space: nowrap; font-style: italic; `; const MessageLabel = styled.span` text-align: left; font-weight: bold; color: ${props => props.theme.secondary} !important; white-space: nowrap; `; const ReplyMessageLabel = styled.span` color: ${props => props.theme.eCashBlue} !important; `; const TxInfo = styled.div` text-align: right; display: flex; align-items: left; flex-direction: column; margin-left: 10px; flex-grow: 2; h3 { color: ${props => props.theme.contrast}; font-size: 14px; font-weight: 700; margin: 0; } .genesis { color: ${props => props.theme.genesisGreen}; } .received { color: ${props => props.theme.eCashBlue}; } h4 { font-size: 12px; color: ${props => props.theme.lightWhite}; margin: 0; } @media screen and (max-width: 500px) { font-size: 0.8rem; } `; const TokenInfo = styled.div` display: flex; flex-grow: 1; justify-content: flex-end; color: ${props => props.outgoing ? props.theme.secondary : props.theme.eCashBlue}; @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.h3` text-align: right; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; `; const TokenName = styled.h4` text-align: right; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; `; const TxWrapper = styled.div` display: flex; align-items: center; border-top: 1px solid rgba(255, 255, 255, 0.12); color: ${props => props.theme.contrast}; padding: 10px 0; flex-wrap: wrap; `; +const Panel = Collapse.Panel; + +const DropdownIconWrapper = styled.div` + display: flex; + align-items: center; + gap: 4px; +`; + +const TextLayer = styled.div` + font-size: 12px; + color: ${props => props.theme.contrast}; +`; + +const DropdownButton = styled.button` + display: flex; + justify-content: flex-end; + background-color: ${props => props.theme.walletBackground}; + border: none; + cursor: pointer; + padding: 0; + &:hover { + div { + color: ${props => props.theme.eCashBlue}!important; + } + svg { + fill: ${props => props.theme.eCashBlue}!important; + } + } +`; +const PanelCtn = styled.div` + display: flex; + justify-content: flex-end; + right: 0; + gap: 8px; +`; + +export const TxLink = styled.a` + color: ${props => props.theme.primary}; +`; + const Tx = ({ data, fiatPrice, fiatCurrency }) => { const txDate = typeof data.blocktime === 'undefined' ? formatDate() : formatDate(data.blocktime, navigator.language); // 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 ? ( + + + - - - - {data.outgoingTx ? ( - - {data.tokenInfo.transactionType === - 'GENESIS' ? ( + + {data.outgoingTx ? ( + <> + {data.tokenTx && + data.tokenInfo + .transactionType === + 'GENESIS' ? ( + + + + ) : ( + + + + )} + + ) : ( + + + + )} + + + {data.outgoingTx ? ( <> - - +{' '} - {data.tokenInfo.qtyReceived.toString()} -   - { - data.tokenInfo - .tokenTicker - } - - - { - data.tokenInfo - .tokenName - } - + {data.tokenTx && + data.tokenInfo + .transactionType === + 'GENESIS' ? ( +

+ Genesis +

+ ) : ( +

+ Sent +

+ )} ) : ( - <> - - -{' '} - {data.tokenInfo.qtySent.toString()} -   - { - data.tokenInfo - .tokenTicker - } - - - { - data.tokenInfo - .tokenName - } - - +

+ Received +

)} -
- ) : ( - - - +{' '} - {data.tokenInfo.qtyReceived.toString()} -   - {data.tokenInfo.tokenTicker} - - - {data.tokenInfo.tokenName} - - - )} +

{txDate}

+ + {data.tokenTx ? ( + + {data.tokenTx && + data.tokenInfo ? ( + <> + + + + {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 + } +

+ )} + + )} +
+ + )} + {data.opReturnMessage && ( + <> + + {data.isCashtabMessage ? ( +

Cashtab Message

+ ) : ( +

+ External Message +

+ )} + {data.isEncryptedMessage ? ( + +  - Encrypted + + ) : ( + '' + )} +
+ {/*unencrypted OP_RETURN Message*/} + {data.opReturnMessage && + !data.isEncryptedMessage ? ( +

+ { + data.opReturnMessage + } +

+ ) : ( + '' + )} + {/*encrypted and wallet is authorized to view OP_RETURN Message*/} + {data.opReturnMessage && + data.isEncryptedMessage && + data.decryptionSuccess ? ( +

+ { + data.opReturnMessage + } +

+ ) : ( + '' + )} + {/*encrypted but wallet is not authorized to view OP_RETURN Message*/} + {data.opReturnMessage && + data.isEncryptedMessage && + !data.decryptionSuccess ? ( + + { + data.opReturnMessage + } + + ) : ( + '' + )} + {!data.outgoingTx && + data.replyAddress ? ( + + Reply To Message + + ) : ( + '' + )} +
+ + )} +
- ) : ( - 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 - } -

- )} - - )} -
- - )} - {data.opReturnMessage && ( - <> - - {data.isCashtabMessage ? ( -

Cashtab Message

- ) : ( -

External Message

- )} - {data.isEncryptedMessage ? ( - -  - Encrypted - - ) : ( - '' - )} -
- {/*unencrypted OP_RETURN Message*/} - {data.opReturnMessage && - !data.isEncryptedMessage ? ( -

{data.opReturnMessage}

- ) : ( - '' - )} - {/*encrypted and wallet is authorized to view OP_RETURN Message*/} - {data.opReturnMessage && - data.isEncryptedMessage && - data.decryptionSuccess ? ( -

{data.opReturnMessage}

- ) : ( - '' - )} - {/*encrypted but wallet is not authorized to view OP_RETURN Message*/} - {data.opReturnMessage && - data.isEncryptedMessage && - !data.decryptionSuccess ? ( - - {data.opReturnMessage} - - ) : ( - '' - )} - {!data.outgoingTx && data.replyAddress ? ( - + + + { + generalNotification( + data.txid, + 'Tx ID copied to clipboard', + ); }} > - Reply To Message - - ) : ( - '' - )} -
- - )} - + + Copy Tx ID + + + + + + + + + + View on be.cash + + + + + + + + + + )} ); }; Tx.propTypes = { data: PropTypes.object, fiatPrice: PropTypes.number, fiatCurrency: PropTypes.string, }; export default Tx; diff --git a/web/cashtab/src/components/Home/TxHistory.js b/web/cashtab/src/components/Home/TxHistory.js index c79a317ee..21364d613 100644 --- a/web/cashtab/src/components/Home/TxHistory.js +++ b/web/cashtab/src/components/Home/TxHistory.js @@ -1,37 +1,27 @@ import React from 'react'; import PropTypes from 'prop-types'; import styled from 'styled-components'; import Tx from './Tx'; -export const TxLink = styled.a` - color: ${props => props.theme.forms.text}; -`; - const TxHistory = ({ txs, fiatPrice, fiatCurrency }) => { return (
{txs.map(tx => ( - - - + data={tx} + fiatPrice={fiatPrice} + fiatCurrency={fiatCurrency} + /> ))}
); }; TxHistory.propTypes = { txs: PropTypes.array, fiatPrice: PropTypes.number, fiatCurrency: PropTypes.string, }; export default TxHistory; diff --git a/web/cashtab/src/components/Home/__tests__/__snapshots__/Home.test.js.snap b/web/cashtab/src/components/Home/__tests__/__snapshots__/Home.test.js.snap index 1a1e37413..f930fc356 100644 --- a/web/cashtab/src/components/Home/__tests__/__snapshots__/Home.test.js.snap +++ b/web/cashtab/src/components/Home/__tests__/__snapshots__/Home.test.js.snap @@ -1,481 +1,481 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP @generated exports[`Wallet with BCH balances 1`] = ` Array [

MigrationTestAlpha

0 XEC
$ NaN USD
,
🎉 Congratulations on your new wallet! 🎉
Start using the wallet immediately to receive XEC payments, or load it up with XEC to send to others
Create eToken

Tokens sent to your eToken address will appear here

, ] `; exports[`Wallet with BCH balances and tokens 1`] = ` Array [

MigrationTestAlpha

0 XEC
$ NaN USD
,
🎉 Congratulations on your new wallet! 🎉
Start using the wallet immediately to receive XEC payments, or load it up with XEC to send to others
Create eToken

Tokens sent to your eToken address will appear here

, ] `; exports[`Wallet with BCH balances and tokens and state field 1`] = ` Array [

MigrationTestAlpha

0.06 XEC
$ NaN USD
,
🎉 Congratulations on your new wallet! 🎉
Start using the wallet immediately to receive XEC payments, or load it up with XEC to send to others
, ] `; exports[`Wallet without BCH balance 1`] = ` Array [

MigrationTestAlpha

0 XEC
$ NaN USD
,
🎉 Congratulations on your new wallet! 🎉
Start using the wallet immediately to receive XEC payments, or load it up with XEC to send to others
Create eToken

Tokens sent to your eToken address will appear here

, ] `; exports[`Without wallet defined 1`] = `

Welcome to Cashtab!

Cashtab is an open source, non-custodial web wallet for eCash .

Want to learn more? Check out the Cashtab documentation.

`; diff --git a/web/cashtab/src/components/Receive/__tests__/__snapshots__/Receive.test.js.snap b/web/cashtab/src/components/Receive/__tests__/__snapshots__/Receive.test.js.snap index 94ce4a59c..9bb24f511 100644 --- a/web/cashtab/src/components/Receive/__tests__/__snapshots__/Receive.test.js.snap +++ b/web/cashtab/src/components/Receive/__tests__/__snapshots__/Receive.test.js.snap @@ -1,534 +1,534 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP @generated exports[`Wallet with BCH balances 1`] = `

Receive XEC

Copied
ecash:qzagy47mvh6qxkvcn3acjnz73rkhkc6y7ccxkrr6zd
ecash: qzagy47m vh6qxkvcn3acjnz73rkhkc6y7c cxkrr6zd
XEC
eToken
`; exports[`Wallet with BCH balances and tokens 1`] = `

Receive XEC

Copied
ecash:qzagy47mvh6qxkvcn3acjnz73rkhkc6y7ccxkrr6zd
ecash: qzagy47m vh6qxkvcn3acjnz73rkhkc6y7c cxkrr6zd
XEC
eToken
`; exports[`Wallet with BCH balances and tokens and state field 1`] = `

Receive XEC

Copied
ecash:qzagy47mvh6qxkvcn3acjnz73rkhkc6y7ccxkrr6zd
ecash: qzagy47m vh6qxkvcn3acjnz73rkhkc6y7c cxkrr6zd
XEC
eToken
`; exports[`Wallet without BCH balance 1`] = `

Receive XEC

Copied
ecash:qzagy47mvh6qxkvcn3acjnz73rkhkc6y7ccxkrr6zd
ecash: qzagy47m vh6qxkvcn3acjnz73rkhkc6y7c cxkrr6zd
XEC
eToken
`; exports[`Without wallet defined 1`] = `

Welcome to Cashtab!

Cashtab is an open source, non-custodial web wallet for eCash .

Want to learn more? Check out the Cashtab documentation.

`; diff --git a/web/cashtab/src/components/Send/__tests__/__snapshots__/Send.test.js.snap b/web/cashtab/src/components/Send/__tests__/__snapshots__/Send.test.js.snap index 26ccd26f6..e7faa995c 100644 --- a/web/cashtab/src/components/Send/__tests__/__snapshots__/Send.test.js.snap +++ b/web/cashtab/src/components/Send/__tests__/__snapshots__/Send.test.js.snap @@ -1,2354 +1,2354 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP @generated exports[`Wallet with BCH balances 1`] = ` Array [

MigrationTestAlpha

You currently have 0 XEC
Deposit some funds to use this feature
,
XEC
max

0 XEC

= $ NaN USD
Advanced
Sign Message
, ] `; exports[`Wallet with BCH balances and tokens 1`] = ` Array [

MigrationTestAlpha

You currently have 0 XEC
Deposit some funds to use this feature
,
XEC
max

0 XEC

= $ NaN USD
Advanced
Sign Message
, ] `; exports[`Wallet with BCH balances and tokens and state field 1`] = ` Array [

MigrationTestAlpha

0.06 XEC
$ NaN USD
,
XEC
max

0 XEC

= $ NaN USD
Advanced
Sign Message
, ] `; exports[`Wallet without BCH balance 1`] = ` Array [

MigrationTestAlpha

You currently have 0 XEC
Deposit some funds to use this feature
,
XEC
max

0 XEC

= $ NaN USD
Advanced
Sign Message
, ] `; exports[`Without wallet defined 1`] = ` Array [
You currently have 0 XEC
Deposit some funds to use this feature
,
XEC
max

0 XEC

= $ NaN USD
Advanced
Sign Message
, ] `; diff --git a/web/cashtab/src/components/Send/__tests__/__snapshots__/SendToken.test.js.snap b/web/cashtab/src/components/Send/__tests__/__snapshots__/SendToken.test.js.snap index ce4787c5a..b149f9337 100644 --- a/web/cashtab/src/components/Send/__tests__/__snapshots__/SendToken.test.js.snap +++ b/web/cashtab/src/components/Send/__tests__/__snapshots__/SendToken.test.js.snap @@ -1,244 +1,244 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP @generated exports[`Wallet with BCH balances and tokens 1`] = `null`; exports[`Wallet with BCH balances and tokens and state field 1`] = `
6.001 TBS
TBS max
`; exports[`Without wallet defined 1`] = `null`; diff --git a/web/cashtab/src/components/Tokens/__tests__/__snapshots__/CreateTokenForm.test.js.snap b/web/cashtab/src/components/Tokens/__tests__/__snapshots__/CreateTokenForm.test.js.snap index e23c98557..1bfa85cc4 100644 --- a/web/cashtab/src/components/Tokens/__tests__/__snapshots__/CreateTokenForm.test.js.snap +++ b/web/cashtab/src/components/Tokens/__tests__/__snapshots__/CreateTokenForm.test.js.snap @@ -1,375 +1,375 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP @generated exports[`Wallet with BCH balances and tokens and state field 1`] = `

Create a Token

Click, or drag file to this area to upload

Only jpg or png accepted

`; 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 452501797..ae66b3a85 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,620 +1,620 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP @generated exports[`Wallet with BCH balances 1`] = ` Array [

MigrationTestAlpha

0 XEC
$ NaN USD
,

Create a Token

You need at least 5.5 XEC ( $ NaN USD ) to create a token

, ] `; exports[`Wallet with BCH balances and tokens 1`] = ` Array [

MigrationTestAlpha

0 XEC
$ NaN USD
,

Create a Token

You need at least 5.5 XEC ( $ NaN USD ) to create a token

, ] `; exports[`Wallet with BCH balances and tokens and state field 1`] = ` Array [

MigrationTestAlpha

0.06 XEC
$ NaN USD
,

Create a Token

Click, or drag file to this area to upload

Only jpg or png accepted

, ] `; exports[`Wallet without BCH balance 1`] = ` Array [

MigrationTestAlpha

0 XEC
$ NaN USD
,

Create a Token

You need at least 5.5 XEC ( $ NaN USD ) to create a token

, ] `; exports[`Without wallet defined 1`] = ` Array [
0 XEC
$ NaN USD
,

Create a Token

You need at least 5.5 XEC ( $ NaN USD ) to create a token

, ] `;