From 2779b5d28ab23efd75da32f54f674792155329a4 Mon Sep 17 00:00:00 2001 From: Mark Sinclair Date: Fri, 1 Apr 2022 18:44:44 +0100 Subject: [PATCH] Password for wallet with routes (#1187) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * new password flow * update global error and load state from children * fix linting * dont load account when creating mnemonic * wallets: provide placeholder functions for ui password * wallet: platform_constants * wallet: swap println to log * UI for existing mnemonic to be use * wallet: inline encryption of wallet file * wallet: tweak error enum names * wallet: general wallet_storage tidy * wallet: tweak some type names * create sign-in context * update sign in functions * move state to context * update pages * connect new rust methods with frontend * update components * remove non-existent method * add separate sign in pages for mnemonic and password * add a hook for clipboard copy * fix workmark svg sizing issue * create step component * use new sign in pages * reorder pages * use clipboard lib directly * ui tweaks * use login type selector * update password strength test + use autofocus prop for password input * start adding routes * restructure with routes * wip * more wip * more wip * reset state where required * wallet: remove unused rust use statements * fix unbond page Co-authored-by: fmtabbara Co-authored-by: Jon Häggblad Co-authored-by: Tommy Verrall --- assets/logo/logo-wordmark.svg | 2 +- nym-wallet/package.json | 1 + nym-wallet/src-tauri/src/main.rs | 3 +- .../src/operations/mixnet/account.rs | 5 +- .../src/wallet_storage/account_data.rs | 9 ++- .../src/wallet_storage/encryption.rs | 10 ++- .../src-tauri/src/wallet_storage/mod.rs | 8 +- .../src-tauri/src/wallet_storage/password.rs | 8 +- nym-wallet/src/context/main.tsx | 28 +++++-- nym-wallet/src/index.tsx | 11 ++- nym-wallet/src/pages/index.ts | 2 +- .../src/pages/send/SendConfirmation.tsx | 3 + nym-wallet/src/pages/send/SendWizard.tsx | 21 +++-- .../src/pages/settings/system-variables.tsx | 10 +-- .../src/pages/sign-in/components/error.tsx | 8 ++ .../components/heading.tsx | 2 +- .../{welcome => sign-in}/components/index.ts | 4 + .../pages/sign-in/components/page-layout.tsx | 33 ++++++++ .../components/password-strength.tsx | 37 +++++++-- .../components/render-page.tsx | 0 .../src/pages/sign-in/components/step.tsx | 30 +++++++ .../pages/sign-in/components/textfields.tsx | 80 ++++++++++++++++++ .../components/word-tiles.tsx | 9 ++- .../src/pages/sign-in/context/index.tsx | 76 +++++++++++++++++ nym-wallet/src/pages/sign-in/index.tsx | 1 + .../pages/sign-in/pages/confirm-mnemonic.tsx | 51 ++++++++++++ .../pages/sign-in/pages/connect-password.tsx | 75 +++++++++++++++++ .../pages/sign-in/pages/create-mnemonic.tsx | 69 ++++++++++++++++ .../pages/sign-in/pages/create-password.tsx | 74 +++++++++++++++++ .../pages/sign-in/pages/existing-account.tsx | 32 ++++++++ nym-wallet/src/pages/sign-in/pages/index.ts | 8 ++ .../pages/sign-in/pages/signin-mnemonic.tsx | 50 ++++++++++++ .../pages/sign-in/pages/signin-password.tsx | 56 +++++++++++++ .../pages/verify-mnemonic.tsx | 40 ++++----- .../src/pages/sign-in/pages/welcome.tsx | 36 +++++++++ .../src/pages/{welcome => sign-in}/types.ts | 8 +- nym-wallet/src/pages/unbond/index.tsx | 24 ++++-- .../pages/welcome/_legacy_create-account.tsx | 56 ------------- .../src/pages/welcome/_legacy_sign-in.tsx | 66 --------------- nym-wallet/src/pages/welcome/index.tsx | 81 ------------------- .../pages/welcome/pages/create-password.tsx | 60 -------------- .../pages/welcome/pages/existing-account.tsx | 55 ------------- nym-wallet/src/pages/welcome/pages/index.ts | 5 -- .../pages/welcome/pages/mnemonic-words.tsx | 34 -------- .../pages/welcome/pages/welcome-content.tsx | 42 ---------- nym-wallet/src/requests/account.ts | 22 +++-- nym-wallet/src/routes/app.tsx | 32 ++++++++ nym-wallet/src/routes/index.tsx | 35 +------- nym-wallet/src/routes/sign-in.tsx | 48 +++++++++++ nym-wallet/src/theme/index.tsx | 1 + 50 files changed, 935 insertions(+), 526 deletions(-) create mode 100644 nym-wallet/src/pages/sign-in/components/error.tsx rename nym-wallet/src/pages/{welcome => sign-in}/components/heading.tsx (93%) rename nym-wallet/src/pages/{welcome => sign-in}/components/index.ts (53%) create mode 100644 nym-wallet/src/pages/sign-in/components/page-layout.tsx rename nym-wallet/src/pages/{welcome => sign-in}/components/password-strength.tsx (69%) rename nym-wallet/src/pages/{welcome => sign-in}/components/render-page.tsx (100%) create mode 100644 nym-wallet/src/pages/sign-in/components/step.tsx create mode 100644 nym-wallet/src/pages/sign-in/components/textfields.tsx rename nym-wallet/src/pages/{welcome => sign-in}/components/word-tiles.tsx (92%) create mode 100644 nym-wallet/src/pages/sign-in/context/index.tsx create mode 100644 nym-wallet/src/pages/sign-in/index.tsx create mode 100644 nym-wallet/src/pages/sign-in/pages/confirm-mnemonic.tsx create mode 100644 nym-wallet/src/pages/sign-in/pages/connect-password.tsx create mode 100644 nym-wallet/src/pages/sign-in/pages/create-mnemonic.tsx create mode 100644 nym-wallet/src/pages/sign-in/pages/create-password.tsx create mode 100644 nym-wallet/src/pages/sign-in/pages/existing-account.tsx create mode 100644 nym-wallet/src/pages/sign-in/pages/index.ts create mode 100644 nym-wallet/src/pages/sign-in/pages/signin-mnemonic.tsx create mode 100644 nym-wallet/src/pages/sign-in/pages/signin-password.tsx rename nym-wallet/src/pages/{welcome => sign-in}/pages/verify-mnemonic.tsx (75%) create mode 100644 nym-wallet/src/pages/sign-in/pages/welcome.tsx rename nym-wallet/src/pages/{welcome => sign-in}/types.ts (71%) delete mode 100644 nym-wallet/src/pages/welcome/_legacy_create-account.tsx delete mode 100644 nym-wallet/src/pages/welcome/_legacy_sign-in.tsx delete mode 100644 nym-wallet/src/pages/welcome/index.tsx delete mode 100644 nym-wallet/src/pages/welcome/pages/create-password.tsx delete mode 100644 nym-wallet/src/pages/welcome/pages/existing-account.tsx delete mode 100644 nym-wallet/src/pages/welcome/pages/index.ts delete mode 100644 nym-wallet/src/pages/welcome/pages/mnemonic-words.tsx delete mode 100644 nym-wallet/src/pages/welcome/pages/welcome-content.tsx create mode 100644 nym-wallet/src/routes/app.tsx create mode 100644 nym-wallet/src/routes/sign-in.tsx diff --git a/assets/logo/logo-wordmark.svg b/assets/logo/logo-wordmark.svg index 14e0208e4a..52512c2665 100644 --- a/assets/logo/logo-wordmark.svg +++ b/assets/logo/logo-wordmark.svg @@ -1,4 +1,4 @@ - + diff --git a/nym-wallet/package.json b/nym-wallet/package.json index 299b34b39f..7d055fb77e 100644 --- a/nym-wallet/package.json +++ b/nym-wallet/package.json @@ -42,6 +42,7 @@ "react-hook-form": "^7.14.2", "react-router-dom": "^5.2.0", "semver": "^6.3.0", + "use-clipboard-copy": "^0.2.0", "yup": "^0.32.9" }, "devDependencies": { diff --git a/nym-wallet/src-tauri/src/main.rs b/nym-wallet/src-tauri/src/main.rs index 0c8f2bbd7b..566d09afeb 100644 --- a/nym-wallet/src-tauri/src/main.rs +++ b/nym-wallet/src-tauri/src/main.rs @@ -18,8 +18,6 @@ mod operations; mod platform_constants; mod state; mod utils; -// temporarily until it is actually used -#[allow(unused)] mod wallet_storage; use crate::menu::AddDefaultSubmenus; @@ -37,6 +35,7 @@ fn main() { .manage(Arc::new(RwLock::new(State::default()))) .invoke_handler(tauri::generate_handler![ mixnet::account::connect_with_mnemonic, + mixnet::account::validate_mnemonic, mixnet::account::create_new_account, mixnet::account::create_new_mnemonic, mixnet::account::create_password, diff --git a/nym-wallet/src-tauri/src/operations/mixnet/account.rs b/nym-wallet/src-tauri/src/operations/mixnet/account.rs index 3fc7d1380e..2e7424103a 100644 --- a/nym-wallet/src-tauri/src/operations/mixnet/account.rs +++ b/nym-wallet/src-tauri/src/operations/mixnet/account.rs @@ -112,9 +112,8 @@ pub async fn create_new_mnemonic() -> Result { } #[tauri::command] -pub fn validate_mnemonic(mnemonic: &str) -> Result<(), BackendError> { - Mnemonic::from_str(mnemonic)?; - Ok(()) +pub fn validate_mnemonic(mnemonic: &str) -> bool { + Mnemonic::from_str(mnemonic).is_ok() } #[tauri::command] diff --git a/nym-wallet/src-tauri/src/wallet_storage/account_data.rs b/nym-wallet/src-tauri/src/wallet_storage/account_data.rs index dd5f9405e8..760208b6b8 100644 --- a/nym-wallet/src-tauri/src/wallet_storage/account_data.rs +++ b/nym-wallet/src-tauri/src/wallet_storage/account_data.rs @@ -2,11 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 use cosmrs::bip32::DerivationPath; -use serde::de::Visitor; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use std::fmt::Formatter; +use serde::{Deserialize, Serialize}; use zeroize::Zeroize; -use zeroize::Zeroizing; use crate::error::BackendError; @@ -23,6 +20,7 @@ pub(crate) struct StoredWallet { } impl StoredWallet { + #[allow(unused)] pub fn version(&self) -> u32 { self.version } @@ -31,6 +29,7 @@ impl StoredWallet { self.accounts.is_empty() } + #[allow(unused)] pub fn len(&self) -> usize { self.accounts.len() } @@ -45,6 +44,7 @@ impl StoredWallet { } } + #[allow(unused)] pub fn encrypted_account_by_index(&self, index: usize) -> Option<&EncryptedAccount> { self.accounts.get(index) } @@ -146,6 +146,7 @@ impl MnemonicAccount { &self.mnemonic } + #[allow(unused)] pub(crate) fn hd_path(&self) -> &DerivationPath { &self.hd_path } diff --git a/nym-wallet/src-tauri/src/wallet_storage/encryption.rs b/nym-wallet/src-tauri/src/wallet_storage/encryption.rs index a8aa27fe84..101dde0417 100644 --- a/nym-wallet/src-tauri/src/wallet_storage/encryption.rs +++ b/nym-wallet/src-tauri/src/wallet_storage/encryption.rs @@ -4,14 +4,13 @@ use super::password::UserPassword; use crate::error::BackendError; use aes_gcm::aead::generic_array::ArrayLength; -use aes_gcm::aead::{Aead, NewAead, Payload}; +use aes_gcm::aead::{Aead, NewAead}; use aes_gcm::{Aes256Gcm, Key, Nonce}; use argon2::{ password_hash::rand_core::{OsRng, RngCore}, Algorithm, Argon2, Params, Version, }; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; -use std::convert::TryFrom; +use serde::{Deserialize, Serialize}; use std::marker::PhantomData; use zeroize::Zeroize; @@ -78,6 +77,7 @@ mod base64 { } impl EncryptedData { + #[allow(unused)] pub(crate) fn encrypt_struct(data: &T, password: &UserPassword) -> Result where T: Serialize, @@ -94,10 +94,12 @@ impl EncryptedData { } impl EncryptedData> { + #[allow(unused)] pub(crate) fn encrypt_data(data: &[u8], password: &UserPassword) -> Result { encrypt_data(data, password) } + #[allow(unused)] pub(crate) fn decrypt_data(&self, password: &UserPassword) -> Result, BackendError> { decrypt_data(self, password) } @@ -159,6 +161,7 @@ fn decrypt( .map_err(|_| BackendError::DecryptionError) } +#[allow(unused)] pub(crate) fn encrypt_data( data: &[u8], password: &UserPassword, @@ -194,6 +197,7 @@ where }) } +#[allow(unused)] pub(crate) fn decrypt_data( encrypted_data: &EncryptedData>, password: &UserPassword, diff --git a/nym-wallet/src-tauri/src/wallet_storage/mod.rs b/nym-wallet/src-tauri/src/wallet_storage/mod.rs index 11fe6f07ce..092fe6dc83 100644 --- a/nym-wallet/src-tauri/src/wallet_storage/mod.rs +++ b/nym-wallet/src-tauri/src/wallet_storage/mod.rs @@ -4,14 +4,11 @@ pub(crate) use crate::wallet_storage::password::{UserPassword, WalletAccountId}; use crate::error::BackendError; -use crate::operations::mixnet::account::create_new_account; use crate::platform_constants::{STORAGE_DIR_NAME, WALLET_INFO_FILENAME}; use crate::wallet_storage::account_data::StoredAccount; -use crate::wallet_storage::encryption::{encrypt_struct, EncryptedData}; +use crate::wallet_storage::encryption::encrypt_struct; use cosmrs::bip32::DerivationPath; -use serde::{Deserialize, Serialize}; use std::fs::{self, create_dir_all, OpenOptions}; -use std::os::unix::prelude::OpenOptionsExt; use std::path::PathBuf; use self::account_data::{EncryptedAccount, StoredWallet}; @@ -33,6 +30,7 @@ pub(crate) fn wallet_login_filepath() -> Result { get_storage_directory().map(|dir| dir.join(WALLET_INFO_FILENAME)) } +#[allow(unused)] pub(crate) fn load_existing_wallet(password: &UserPassword) -> Result { let store_dir = get_storage_directory()?; let filepath = store_dir.join(WALLET_INFO_FILENAME); @@ -154,9 +152,7 @@ pub(crate) fn remove_wallet_login_information_at_file( #[cfg(test)] mod tests { use super::*; - use crate::wallet_storage::encryption::encrypt_data; use config::defaults::COSMOS_DERIVATION_PATH; - use std::path::Path; use tempfile::tempdir; // I'm not 100% sure how to feel about having to touch the file system at all diff --git a/nym-wallet/src-tauri/src/wallet_storage/password.rs b/nym-wallet/src-tauri/src/wallet_storage/password.rs index 894576f4b4..04b85277a1 100644 --- a/nym-wallet/src-tauri/src/wallet_storage/password.rs +++ b/nym-wallet/src-tauri/src/wallet_storage/password.rs @@ -3,7 +3,7 @@ use std::fmt; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use serde::{Deserialize, Serialize}; use zeroize::Zeroize; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -22,9 +22,9 @@ impl AsRef for WalletAccountId { } impl fmt::Display for WalletAccountId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } } // simple wrapper for String that will get zeroized on drop diff --git a/nym-wallet/src/context/main.tsx b/nym-wallet/src/context/main.tsx index 0209364494..dc6091c8de 100644 --- a/nym-wallet/src/context/main.tsx +++ b/nym-wallet/src/context/main.tsx @@ -1,10 +1,11 @@ import React, { useMemo, createContext, useEffect, useState } from 'react'; import { useHistory } from 'react-router-dom'; import { useSnackbar } from 'notistack'; +import { TLoginType } from 'src/pages/sign-in/types'; import { Account, Network, TCurrency, TMixnodeBondDetails } from '../types'; import { TUseuserBalance, useGetBalance } from '../hooks/useGetBalance'; import { config } from '../../config'; -import { getMixnodeBondDetails, selectNetwork, signInWithMnemonic, signOut } from '../requests'; +import { getMixnodeBondDetails, selectNetwork, signInWithMnemonic, signInWithPassword, signOut } from '../requests'; import { currencyMap } from '../utils'; import { Console } from '../utils/console'; @@ -32,11 +33,14 @@ type TClientContext = { currency?: TCurrency; isLoading: boolean; error?: string; + setIsLoading: (isLoading: boolean) => void; + setError: (value?: string) => void; switchNetwork: (network: Network) => void; getBondDetails: () => Promise; handleShowSettings: () => void; handleShowAdmin: () => void; - logIn: (mnemonic: string) => void; + logIn: (opts: { type: 'mnemonic' | 'password'; value: string }) => void; + signInWithPassword: (password: string) => void; logOut: () => void; }; @@ -90,17 +94,24 @@ export const ClientContextProvider = ({ children }: { children: React.ReactNode refreshAccount(); }, [network]); - const logIn = async (mnemonic: string) => { + const logIn = async ({ type, value }: { type: TLoginType; value: string }) => { + if (value.length === 0) { + setError(`A ${type} must be provided`); + return; + } try { setIsLoading(true); - await signInWithMnemonic(mnemonic || ''); - await getBondDetails(); + if (type === 'mnemonic') { + await signInWithMnemonic(value); + } else { + await signInWithPassword(value); + } setNetwork('MAINNET'); + history.push('/balance'); } catch (e) { - setIsLoading(false); setError(e as string); } finally { - history.push('/balance'); + setIsLoading(false); } }; @@ -131,6 +142,9 @@ export const ClientContextProvider = ({ children }: { children: React.ReactNode showSettings, network, currency, + setIsLoading, + setError, + signInWithPassword, switchNetwork, getBondDetails, handleShowSettings, diff --git a/nym-wallet/src/index.tsx b/nym-wallet/src/index.tsx index f05b529d07..2400a8b00a 100644 --- a/nym-wallet/src/index.tsx +++ b/nym-wallet/src/index.tsx @@ -3,13 +3,14 @@ import ReactDOM from 'react-dom'; import { ErrorBoundary } from 'react-error-boundary'; import { BrowserRouter as Router } from 'react-router-dom'; import { SnackbarProvider } from 'notistack'; -import { Routes } from './routes'; +import { AppRoutes, SignInRoutes } from './routes'; import { ClientContext, ClientContextProvider } from './context/main'; import { ApplicationLayout } from './layouts'; -import { Admin, Welcome, Settings } from './pages'; +import { Admin, Settings } from './pages'; import { ErrorFallback } from './components'; import { NymWalletTheme, WelcomeTheme } from './theme'; import { maximizeWindow } from './utils'; +import { SignInProvider } from './pages/sign-in/context'; const App = () => { const { clientDetails } = useContext(ClientContext); @@ -20,14 +21,16 @@ const App = () => { return !clientDetails ? ( - + + + ) : ( - + ); diff --git a/nym-wallet/src/pages/index.ts b/nym-wallet/src/pages/index.ts index dc00ac2bb2..6bc5c9fdbc 100644 --- a/nym-wallet/src/pages/index.ts +++ b/nym-wallet/src/pages/index.ts @@ -5,7 +5,7 @@ export * from './delegate'; export * from './internal-docs'; export * from './receive'; export * from './send'; -export * from './welcome'; +export * from './sign-in'; export * from './settings'; export * from './unbond'; export * from './undelegate'; diff --git a/nym-wallet/src/pages/send/SendConfirmation.tsx b/nym-wallet/src/pages/send/SendConfirmation.tsx index 560136bc21..fb2d77fb27 100644 --- a/nym-wallet/src/pages/send/SendConfirmation.tsx +++ b/nym-wallet/src/pages/send/SendConfirmation.tsx @@ -16,6 +16,9 @@ export const SendConfirmation = ({ isLoading: boolean; }) => { const { userBalance, currency, network } = useContext(ClientContext); + + if (!data && !error && !isLoading) return null; + return ( { px: 3, }} > - {activeStep === 0 ? ( - - ) : activeStep === 1 ? ( - - ) : ( - - )} + {activeStep === 0 && } + {activeStep === 1 && } + { color="primary" disableElevation data-testid="button" - onClick={activeStep === 0 ? handleNextStep : activeStep === 1 ? handleSend : handleFinish} + onClick={() => { + switch (activeStep) { + case 0: + return handleNextStep(); + case 1: + return handleSend(); + default: + return handleFinish(); + } + }} disabled={!!(methods.formState.errors.amount || methods.formState.errors.to || isLoading)} size="large" > diff --git a/nym-wallet/src/pages/settings/system-variables.tsx b/nym-wallet/src/pages/settings/system-variables.tsx index 11bf6c0218..a0276b4733 100644 --- a/nym-wallet/src/pages/settings/system-variables.tsx +++ b/nym-wallet/src/pages/settings/system-variables.tsx @@ -139,13 +139,13 @@ export const SystemVariables = ({ pt: 0, }} > - {nodeUpdateResponse === 'success' ? ( + {nodeUpdateResponse === 'success' && ( Node successfully updated - ) : nodeUpdateResponse === 'failed' ? ( - Node update failed - ) : ( - )} + {nodeUpdateResponse === 'failed' && ( + Node update failed + )} + {!nodeUpdateResponse && } - - - - - {inputError && ( - - - {inputError} - - - )} - - - ); -}; diff --git a/nym-wallet/src/pages/welcome/index.tsx b/nym-wallet/src/pages/welcome/index.tsx deleted file mode 100644 index c23444dbdf..0000000000 --- a/nym-wallet/src/pages/welcome/index.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import React, { useContext, useState } from 'react'; -import { NymLogo } from '@nymproject/react'; -import { CircularProgress, Stack, Box } from '@mui/material'; -import { ExistingAccount, WelcomeContent } from './pages'; -import { TPages } from './types'; -import { RenderPage } from './components'; -import { CreateAccountContent } from './_legacy_create-account'; -import { ClientContext } from '../../context/main'; - -// const testMnemonic = -// 'futuristic big receptive caption saw hug odd spoon internal dime bike rake helpless left distribution gusty eyes beg enormous word influence trashy pets curl'; -// -// const mnemonicToArray = (mnemonic: string): TMnemonicWords => -// mnemonic -// .split(' ') -// .reduce((a, c: string, index) => [...a, { name: c, index: index + 1, disabled: false }], [] as TMnemonicWords); - -export const Welcome = () => { - const [page, setPage] = useState('welcome'); - // const [mnemonicWords, setMnemonicWords] = useState(); - - const { isLoading } = useContext(ClientContext); - - // useEffect(() => { - // const mnemonicArray = mnemonicToArray(testMnemonic) - // setMnemonicWords(mnemonicArray) - // }, []) - - return ( - - - {isLoading ? ( - - ) : ( - - - - setPage('existing account')} - onCreateAccountComplete={() => setPage('legacy create account')} - page="welcome" - /> - - setPage('existing account')} /> - {/* setPage('verify mnemonic')} - onPrev={() => setPage('welcome')} - page="create account" - /> - setPage('create password')} - page="verify mnemonic" - /> - */} - setPage('welcome')} page="existing account" /> - - - )} - - - ); -}; diff --git a/nym-wallet/src/pages/welcome/pages/create-password.tsx b/nym-wallet/src/pages/welcome/pages/create-password.tsx deleted file mode 100644 index 9d1ee759e5..0000000000 --- a/nym-wallet/src/pages/welcome/pages/create-password.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import React, { useState } from 'react'; -import { Button, FormControl, Grid, IconButton, Stack, TextField } from '@mui/material'; -import { VisibilityOff, Visibility } from '@mui/icons-material'; -import { Subtitle, Title, PasswordStrength } from '../components'; - -export const CreatePassword = () => { - const [password, setPassword] = useState(''); - const [confirmedPassword, setConfirmedPassword] = useState(); - const [showPassword, setShowPassword] = useState(false); - const [showConfirmedPassword, setShowConfirmedPassword] = useState(false); - - return ( - <> - - - - - - - setPassword(e.target.value)} - type={showPassword ? 'input' : 'password'} - InputProps={{ - endAdornment: ( - setShowPassword((show) => !show)}> - {showPassword ? : } - - ), - }} - /> - - setConfirmedPassword(e.target.value)} - type={showConfirmedPassword ? 'input' : 'password'} - InputProps={{ - endAdornment: ( - setShowConfirmedPassword((show) => !show)}> - {showConfirmedPassword ? : } - - ), - }} - /> - - - - - - - ); -}; diff --git a/nym-wallet/src/pages/welcome/pages/existing-account.tsx b/nym-wallet/src/pages/welcome/pages/existing-account.tsx deleted file mode 100644 index e0a4800cd8..0000000000 --- a/nym-wallet/src/pages/welcome/pages/existing-account.tsx +++ /dev/null @@ -1,55 +0,0 @@ -/* eslint-disable react/no-unused-prop-types */ -import React, { useContext, useState } from 'react'; -import { Alert, Button, Stack, TextField } from '@mui/material'; -import { Subtitle } from '../components'; -import { ClientContext } from '../../../context/main'; -import { TPages } from '../types'; - -export const ExistingAccount: React.FC<{ page: TPages; onPrev: () => void }> = ({ onPrev }) => { - const [mnemonic, setMnemonic] = useState(''); - - const { logIn, error } = useContext(ClientContext); - - const handleSignIn = async () => { - await logIn(mnemonic); - }; - - const handleSignInOnEnter = ({ key }: React.KeyboardEvent) => { - if (key.toLowerCase() === 'enter') { - logIn(mnemonic); - } - }; - - return ( - - - setMnemonic(e.target.value)} - multiline - rows={5} - fullWidth - onKeyDown={handleSignInOnEnter} - /> - {error && ( - - {error} - - )} - - - - - ); -}; diff --git a/nym-wallet/src/pages/welcome/pages/index.ts b/nym-wallet/src/pages/welcome/pages/index.ts deleted file mode 100644 index 0553bb50f3..0000000000 --- a/nym-wallet/src/pages/welcome/pages/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from './welcome-content'; -export * from './mnemonic-words'; -export * from './verify-mnemonic'; -export * from './create-password'; -export * from './existing-account'; diff --git a/nym-wallet/src/pages/welcome/pages/mnemonic-words.tsx b/nym-wallet/src/pages/welcome/pages/mnemonic-words.tsx deleted file mode 100644 index efad61b414..0000000000 --- a/nym-wallet/src/pages/welcome/pages/mnemonic-words.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react'; -import { Alert, Button, Typography } from '@mui/material'; -import { WordTiles } from '../components'; -import { TMnemonicWords } from '../types'; - -export const MnemonicWords = ({ - mnemonicWords, - onNext, - onPrev, -}: { - mnemonicWords?: TMnemonicWords; - onNext: () => void; - onPrev: () => void; -}) => ( - <> - Write down your mnemonic - - Please store your mnemonic in a safe place. This is the only way to access your wallet! - - - - - -); diff --git a/nym-wallet/src/pages/welcome/pages/welcome-content.tsx b/nym-wallet/src/pages/welcome/pages/welcome-content.tsx deleted file mode 100644 index dbbfe7a0fd..0000000000 --- a/nym-wallet/src/pages/welcome/pages/welcome-content.tsx +++ /dev/null @@ -1,42 +0,0 @@ -/* eslint-disable react/no-unused-prop-types */ -import React from 'react'; -import { Button, Stack } from '@mui/material'; -import { SubtitleSlick, Title } from '../components'; -import { TPages } from '../types'; - -export const WelcomeContent: React.FC<{ - page: TPages; - onUseExisting: () => void; - onCreateAccountComplete: () => void; -}> = ({ onUseExisting, onCreateAccountComplete }) => ( - <> - - - - - - - -); diff --git a/nym-wallet/src/requests/account.ts b/nym-wallet/src/requests/account.ts index f8bf6cfc61..f6d75e5bf6 100644 --- a/nym-wallet/src/requests/account.ts +++ b/nym-wallet/src/requests/account.ts @@ -1,14 +1,10 @@ import { invoke } from '@tauri-apps/api'; -import { Account, TCreateAccount } from '../types'; +import { Account } from '../types'; -export const createAccount = async (): Promise => { - const res: TCreateAccount = await invoke('create_new_account'); - return res; -}; +export const createMnemonic = async (): Promise => invoke('create_new_mnemonic'); -export const createMnemonic = async (): Promise => { - const res: string = await invoke('create_new_mnemonic'); - return res; +export const createPassword = async ({ mnemonic, password }: { mnemonic: string; password: string }): Promise => { + await invoke('create_password', { mnemonic, password }); }; export const signInWithMnemonic = async (mnemonic: string): Promise => { @@ -16,6 +12,16 @@ export const signInWithMnemonic = async (mnemonic: string): Promise => return res; }; +export const validateMnemonic = async (mnemonic: string): Promise => { + const res: boolean = await invoke('validate_mnemonic', { mnemonic }); + return res; +}; + +export const signInWithPassword = async (password: string): Promise => { + const res: Account = await invoke('sign_in_with_password', { password }); + return res; +}; + export const signOut = async (): Promise => { await invoke('logout'); }; diff --git a/nym-wallet/src/routes/app.tsx b/nym-wallet/src/routes/app.tsx new file mode 100644 index 0000000000..3b393bb8e4 --- /dev/null +++ b/nym-wallet/src/routes/app.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { Switch, Route } from 'react-router-dom'; +import { Bond, Balance, Delegate, InternalDocs, Receive, Send, Unbond, Undelegate } from '../pages'; + +export const AppRoutes = () => ( + + + + + + + + + + + + + + + + + + + + + + + + + + +); diff --git a/nym-wallet/src/routes/index.tsx b/nym-wallet/src/routes/index.tsx index 039e3a447d..d2037fa0e4 100644 --- a/nym-wallet/src/routes/index.tsx +++ b/nym-wallet/src/routes/index.tsx @@ -1,33 +1,2 @@ -import React from 'react'; -import { Switch, Route } from 'react-router-dom'; -import { Balance } from '../pages/balance'; -import { Bond, Delegate, InternalDocs, Receive, Send, Unbond, Undelegate } from '../pages'; - -export const Routes = () => ( - - - - - - - - - - - - - - - - - - - - - - - - - - -); +export * from './app'; +export * from './sign-in'; diff --git a/nym-wallet/src/routes/sign-in.tsx b/nym-wallet/src/routes/sign-in.tsx new file mode 100644 index 0000000000..2d161641cd --- /dev/null +++ b/nym-wallet/src/routes/sign-in.tsx @@ -0,0 +1,48 @@ +import React from 'react'; +import { Switch, Route } from 'react-router-dom'; +import { PageLayout } from 'src/pages/sign-in/components'; +import { + CreateMnemonic, + CreatePassword, + ExistingAccount, + SignInMnemonic, + SignInPassword, + VerifyMnemonic, + WelcomeContent, + ConnectPassword, +} from 'src/pages/sign-in/pages'; +import { ConfirmMnemonic } from 'src/pages/sign-in/pages/confirm-mnemonic'; + +export const SignInRoutes = () => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +); diff --git a/nym-wallet/src/theme/index.tsx b/nym-wallet/src/theme/index.tsx index 70470845e6..3d59f21892 100644 --- a/nym-wallet/src/theme/index.tsx +++ b/nym-wallet/src/theme/index.tsx @@ -8,6 +8,7 @@ import { NymWalletThemeWithMode } from './NymWalletTheme'; /** * Provides the theme for the Network Explorer by reacting to the light/dark mode choice stored in the app context. */ + export const NymWalletTheme: React.FC = ({ children }) => { const { mode } = useContext(ClientContext); return {children};