diff --git a/cashtab/package-lock.json b/cashtab/package-lock.json --- a/cashtab/package-lock.json +++ b/cashtab/package-lock.json @@ -1,12 +1,12 @@ { "name": "cashtab", - "version": "2.18.5", + "version": "2.19.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cashtab", - "version": "2.18.5", + "version": "2.19.0", "dependencies": { "@ant-design/icons": "^5.3.0", "@bitgo/utxo-lib": "^9.33.0", diff --git a/cashtab/package.json b/cashtab/package.json --- a/cashtab/package.json +++ b/cashtab/package.json @@ -1,6 +1,6 @@ { "name": "cashtab", - "version": "2.18.5", + "version": "2.19.0", "private": true, "scripts": { "start": "node scripts/start.js", diff --git a/cashtab/src/components/App/App.js b/cashtab/src/components/App/App.js --- a/cashtab/src/components/App/App.js +++ b/cashtab/src/components/App/App.js @@ -11,6 +11,7 @@ ReceiveIcon, SettingsIcon, AirdropIcon, + WalletIcon, ThemedSignAndVerifyMsg, ThemedUserProfileIcon, SwapIcon, @@ -24,6 +25,7 @@ import SendXec from 'components/Send/SendXec'; import SendToken from 'components/Send/SendToken'; import Airdrop from 'components/Airdrop/Airdrop'; +import BackupWallet from 'components/BackupWallet/BackupWallet'; import Alias from 'components/Alias/Alias'; import Etokens from 'components/Etokens/Etokens'; import Configure from 'components/Configure/Configure'; @@ -554,6 +556,13 @@ )} + {selectedKey === + 'backup' && ( + + Wallet Backup + + + )} {selectedKey === 'configure' && ( @@ -658,6 +667,12 @@ /> } /> + + } + /> + navigate('/backup')} + > + {' '} +

Wallet Backup

+ +
{ const mockedChronik = await initializeCashtabStateForTests( diff --git a/cashtab/src/components/BackupWallet/BackupWallet.js b/cashtab/src/components/BackupWallet/BackupWallet.js new file mode 100644 --- /dev/null +++ b/cashtab/src/components/BackupWallet/BackupWallet.js @@ -0,0 +1,93 @@ +// Copyright (c) 2024 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import React, { useState } from 'react'; +import { WalletContext } from 'wallet/context'; +import styled from 'styled-components'; +import CopyToClipboard from 'components/Common/CopyToClipboard'; +import Seed from 'components/Common/Seed'; +import Switch from 'components/Common/Switch'; +import { getUserLocale } from 'helpers'; +import { Alert, Info } from 'components/Common/Atoms'; + +const BackupFlex = styled.div` + margin: 12px 0; + display: flex; + flex-direction: column; + align-items: center; + row-gap: 48px; + color: ${props => props.theme.contrast}; + justify-content: flex-start; +`; +const FlexRow = styled.div` + display: flex; + align-items: center; + justify-content: center; + gap: 12px; +`; +const SwitchRow = styled.div` + display: flex; + align-items: center; + justify-content: flex-start; + width: 100%; + gap: 12px; +`; +const SwitchLabel = styled.div``; + +const BackupWallet = () => { + const ContextValue = React.useContext(WalletContext); + const { cashtabState } = ContextValue; + const { wallets } = cashtabState; + + const userLocale = getUserLocale(navigator); + const [showSeed, setShowSeed] = useState(false); + + const wallet = wallets.length > 0 ? wallets[0] : false; + + return ( + + + + ℹ️ Your seed phrase is the only way to restore your wallet. + Write it down. Keep it safe. + + + + + + ⚠️ NEVER SHARE YOUR SEED PHRASE + {!userLocale.includes('en-') && ( + <> +
+
+ ⚠️ STORE YOUR SEED PHRASE IN ENGLISH + + )} +
+
+
+ + setShowSeed(!showSeed)} + /> + I understand, show me my seed phrase. + + + {showSeed && ( + + + + )} + +
+ ); +}; + +export default BackupWallet; diff --git a/cashtab/src/components/Common/Atoms.js b/cashtab/src/components/Common/Atoms.js --- a/cashtab/src/components/Common/Atoms.js +++ b/cashtab/src/components/Common/Atoms.js @@ -74,3 +74,16 @@ color: ${props => props.theme.contrast}; font-size: 18px; `; + +export const Alert = styled.div` + background-color: #fff2f0; + border-radius: 12px; + color: red; + padding: 12px; +`; +export const Info = styled.div` + background-color: #fff2f0; + border-radius: 12px; + color: ${props => props.theme.eCashBlue}; + padding: 12px; +`; diff --git a/cashtab/src/components/Common/CustomIcons.js b/cashtab/src/components/Common/CustomIcons.js --- a/cashtab/src/components/Common/CustomIcons.js +++ b/cashtab/src/components/Common/CustomIcons.js @@ -141,6 +141,9 @@ export const ThemedSignAndVerifyMsg = styled(Audit)` min-width: 24px; `; +export const WalletIcon = styled(ThemedWalletOutlined)` + min-width: 24px; +`; export const ThemedUserProfileIcon = styled(User)` height: 33px; diff --git a/cashtab/src/components/Configure/Configure.js b/cashtab/src/components/Configure/Configure.js --- a/cashtab/src/components/Configure/Configure.js +++ b/cashtab/src/components/Configure/Configure.js @@ -5,7 +5,7 @@ import React, { useState, useEffect } from 'react'; import styled from 'styled-components'; import { useLocation, Link } from 'react-router-dom'; -import { Collapse, Form, Alert, Tooltip, Checkbox } from 'antd'; +import { Collapse, Form, Tooltip } from 'antd'; import { Row, Col } from 'antd'; import { LockFilled } from '@ant-design/icons'; import { WalletContext } from 'wallet/context'; @@ -18,7 +18,6 @@ SecondaryButton, } from 'components/Common/PrimaryButton'; import { - ThemedCopyOutlined, ThemedWalletOutlined, ThemedDollarOutlined, ThemedSettingOutlined, @@ -29,7 +28,6 @@ ThemedCopySolid, ThemedTrashcanOutlined, ThemedEditOutlined, - WarningIcon, ThemedXIcon, ThemedFacebookIcon, ThemedGithubIcon, @@ -59,7 +57,7 @@ import { toast } from 'react-toastify'; import { Input, ModalInput, InputFlex } from 'components/Common/Inputs'; import Switch from 'components/Common/Switch'; -import Seed from 'components/Common/Seed'; +import { Info } from 'components/Common/Atoms'; const { Panel } = Collapse; @@ -375,26 +373,22 @@ `; const StyledConfigure = styled.div` + margin: 12px 0; h2 { color: ${props => props.theme.contrast}; font-size: 25px; } svg { fill: ${props => props.theme.eCashBlue}; - } p { color: ${props => props.theme.darkBlue}; } - .ant-alert { - color: ${props => props.theme.lightGrey} - font-size: 14px; - } - .ant-collapse-header{ - .anticon{ + .ant-collapse-header { + .anticon { flex: 1; } - .seedPhrase{ + .seedPhrase { flex: 2; } } @@ -463,8 +457,6 @@ const [walletDeleteConfirmationError, setWalletDeleteConfirmationError] = useState(false); const [seedInput, openSeedInput] = useState(false); - const [revealSeed, setRevealSeed] = useState(false); - const [showTranslationWarning, setShowTranslationWarning] = useState(false); const [savedWalletContactModal, setSavedWalletContactModal] = useState(false); @@ -547,11 +539,6 @@ }; useEffect(() => { - const detectedBrowserLang = navigator.language; - if (!detectedBrowserLang.includes('en-')) { - setShowTranslationWarning(true); - } - handleContactListRouting(); }, []); @@ -1229,70 +1216,12 @@ /> )} -

- Backup your wallet -

- - {showTranslationWarning && ( - - )} - {wallet && wallet.mnemonic && ( - - - Click to reveal seed phrase - - } - > -

- { - <> - -
- NEVER share your seed phrase. -
- DO NOT enter it into 3rd party - websites. -
-
- { - setRevealSeed(!revealSeed); - }} - > - I understand, show me my seed phrase. - -
- - } -

- {wallet && wallet.mnemonic && revealSeed && ( - - - - )} -
-
- )} - + + ℹ️ Backup wallet has moved +
+
Go to the Backup Wallet screen + to see your seed phrase +

Manage Wallets

diff --git a/cashtab/src/components/Home/Home.js b/cashtab/src/components/Home/Home.js --- a/cashtab/src/components/Home/Home.js +++ b/cashtab/src/components/Home/Home.js @@ -10,6 +10,7 @@ import ApiError from 'components/Common/ApiError'; import { getWalletState } from 'utils/cashMethods'; import Receive from 'components/Receive/Receive'; +import { Alert } from 'components/Common/Atoms'; export const Tabs = styled.div` margin: auto; @@ -113,13 +114,6 @@ padding: 6px 0 12px 0; `; -const BackupWalletAlert = styled.div` - background-color: #fff2f0; - border-radius: 12px; - color: red; - padding: 12px; -`; - const Home = () => { const ContextValue = React.useContext(WalletContext); const { fiatPrice, apiError, cashtabState } = ContextValue; @@ -145,7 +139,7 @@ /> {!hasHistory && ( <> - +

Backup your wallet

@@ -154,7 +148,7 @@ safe place.{' '} Do not share your backup with anyone.

-
+
)}