style: home screen first pass

This commit is contained in:
Cody Bender 2024-08-09 13:19:21 -04:00
parent afd09dc4c1
commit cca89775aa
9 changed files with 399 additions and 254 deletions

View File

@ -13,6 +13,7 @@
"@ethersproject/shims": "^5.7.0", "@ethersproject/shims": "^5.7.0",
"@hookform/resolvers": "^3.3.4", "@hookform/resolvers": "^3.3.4",
"@json-rpc-tools/utils": "^1.7.6", "@json-rpc-tools/utils": "^1.7.6",
"@mui/lab": "^5.0.0-alpha.173",
"@mui/material": "^5.16.4", "@mui/material": "^5.16.4",
"@react-navigation/elements": "^1.3.30", "@react-navigation/elements": "^1.3.30",
"@react-navigation/native": "^6.1.10", "@react-navigation/native": "^6.1.10",

View File

@ -8,6 +8,11 @@
<meta name="theme-color" content="#000000" /> <meta name="theme-color" content="#000000" />
<meta name="description" content="Laconic Wallet Web App" /> <meta name="description" content="Laconic Wallet Web App" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=DM+Mono:ital,wght@0,300;0,400;0,500;1,300;1,400;1,500&display=swap"
rel="stylesheet" />
<!-- <!--
manifest.json provides metadata used when your web app is installed on a manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/ user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/

View File

@ -1,9 +1,7 @@
import React from 'react'; import React from "react";
import { View } from 'react-native';
import { Text } from 'react-native-paper';
import { Account } from '../types'; import { Account } from "../types";
import styles from '../styles/stylesheet'; import { Box, Stack, Typography } from "@mui/material";
interface AccountDetailsProps { interface AccountDetailsProps {
account: Account | undefined; account: Account | undefined;
@ -11,20 +9,28 @@ interface AccountDetailsProps {
const AccountDetails: React.FC<AccountDetailsProps> = ({ account }) => { const AccountDetails: React.FC<AccountDetailsProps> = ({ account }) => {
return ( return (
<View style={styles.accountContainer}> <Box sx={{ marginY: 4 }}>
<Text variant="bodyLarge" selectable={true}> <Stack spacing={1}>
<Text style={styles.highlight}>Address: </Text> <Stack flexDirection="row">
{account?.address} <Typography color="secondary" sx={{ mr: 1 }}>
</Text> Address:
<Text variant="bodyLarge" selectable={true}> </Typography>
<Text style={styles.highlight}>Public Key: </Text> <Typography color="text.primary">{account?.address}</Typography>
{account?.pubKey} </Stack>
</Text> </Stack>
<Text variant="bodyLarge"> <Stack flexDirection="row">
<Text style={styles.highlight}>HD Path: </Text> <Typography color="secondary" sx={{ mr: 1 }}>
{account?.hdPath} Public Key:
</Text> </Typography>
</View> <Typography color="text.primary">{account?.pubKey}</Typography>
</Stack>
<Stack flexDirection="row">
<Typography color="secondary" sx={{ mr: 1 }}>
HD Path:
</Typography>
<Typography color="text.primary">{account?.hdPath}</Typography>
</Stack>
</Box>
); );
}; };

View File

@ -1,22 +1,23 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from "react";
import { TouchableOpacity, View } from 'react-native'; import { TouchableOpacity, View } from "react-native";
import { Button, List, Text, useTheme } from 'react-native-paper'; import { List } from "react-native-paper";
import { useNavigation } from '@react-navigation/native'; import { useNavigation } from "@react-navigation/native";
import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { NativeStackNavigationProp } from "@react-navigation/native-stack";
import { StackParamsList, Account } from '../types'; import { StackParamsList, Account } from "../types";
import { addAccount } from '../utils/accounts'; import { addAccount } from "../utils/accounts";
import styles from '../styles/stylesheet'; import HDPathDialog from "./HDPathDialog";
import HDPathDialog from './HDPathDialog'; import AccountDetails from "./AccountDetails";
import AccountDetails from './AccountDetails'; import { useAccounts } from "../context/AccountsContext";
import { useAccounts } from '../context/AccountsContext'; import { useWalletConnect } from "../context/WalletConnectContext";
import { useWalletConnect } from '../context/WalletConnectContext'; import { useNetworks } from "../context/NetworksContext";
import { useNetworks } from '../context/NetworksContext'; import ConfirmDialog from "./ConfirmDialog";
import ConfirmDialog from './ConfirmDialog'; import { getNamespaces } from "../utils/wallet-connect/helpers";
import { getNamespaces } from '../utils/wallet-connect/helpers'; import ShowPKDialog from "./ShowPKDialog";
import ShowPKDialog from './ShowPKDialog'; import { setInternetCredentials } from "../utils/key-store";
import { setInternetCredentials } from '../utils/key-store'; import { Button, Link, Stack } from "@mui/material";
import { LoadingButton } from "@mui/lab";
const Accounts = () => { const Accounts = () => {
const navigation = const navigation =
@ -27,16 +28,14 @@ const Accounts = () => {
const { networksData, selectedNetwork, setNetworksData, setSelectedNetwork } = const { networksData, selectedNetwork, setNetworksData, setSelectedNetwork } =
useNetworks(); useNetworks();
const {web3wallet} = useWalletConnect(); const { web3wallet } = useWalletConnect();
const [expanded, setExpanded] = useState(false); const [expanded, setExpanded] = useState(false);
const [isAccountCreating, setIsAccountCreating] = useState(false); const [isAccountCreating, setIsAccountCreating] = useState(false);
const [hdDialog, setHdDialog] = useState(false); const [hdDialog, setHdDialog] = useState(false);
const [pathCode, setPathCode] = useState(''); const [pathCode, setPathCode] = useState("");
const [deleteNetworkDialog, setDeleteNetworkDialog] = const [deleteNetworkDialog, setDeleteNetworkDialog] =
useState<boolean>(false); useState<boolean>(false);
const theme = useTheme();
const handlePress = () => setExpanded(!expanded); const handlePress = () => setExpanded(!expanded);
const hideDeleteNetworkDialog = () => setDeleteNetworkDialog(false); const hideDeleteNetworkDialog = () => setDeleteNetworkDialog(false);
@ -88,7 +87,7 @@ const Accounts = () => {
}; };
const renderAccountItems = () => const renderAccountItems = () =>
accounts.map(account => ( accounts.map((account) => (
<List.Item <List.Item
key={account.index} key={account.index}
title={`Account ${account.index + 1}`} title={`Account ${account.index + 1}`}
@ -101,12 +100,12 @@ const Accounts = () => {
const handleRemove = async () => { const handleRemove = async () => {
const updatedNetworks = networksData.filter( const updatedNetworks = networksData.filter(
networkData => selectedNetwork!.networkId !== networkData.networkId, (networkData) => selectedNetwork!.networkId !== networkData.networkId,
); );
await setInternetCredentials( await setInternetCredentials(
'networks', "networks",
'_', "_",
JSON.stringify(updatedNetworks), JSON.stringify(updatedNetworks),
); );
@ -128,91 +127,72 @@ const Accounts = () => {
<List.Accordion <List.Accordion
title={`Account ${currentIndex + 1}`} title={`Account ${currentIndex + 1}`}
expanded={expanded} expanded={expanded}
onPress={handlePress}> onPress={handlePress}
>
{renderAccountItems()} {renderAccountItems()}
</List.Accordion> </List.Accordion>
<View style={styles.addAccountButton}> <Stack direction="row" spacing={3} sx={{ mt: 4 }}>
<Button <LoadingButton
mode="contained" variant="contained"
onPress={addAccountHandler} onClick={addAccountHandler}
loading={isAccountCreating} loading={isAccountCreating}
disabled={isAccountCreating}> disabled={isAccountCreating}
{isAccountCreating ? 'Adding' : 'Add Account'} >
</Button> {isAccountCreating ? "Adding" : "Add Account"}
</View> </LoadingButton>
<View style={styles.addAccountButton}>
<Button <Button
mode="contained" variant="contained"
onPress={() => { onClick={() => {
setHdDialog(true); setHdDialog(true);
setPathCode(`m/44'/${selectedNetwork!.coinType}'/`); setPathCode(`m/44'/${selectedNetwork!.coinType}'/`);
}}> }}
>
Add Account from HD path Add Account from HD path
</Button> </Button>
</View> </Stack>
<AccountDetails account={accounts[currentIndex]} /> <AccountDetails account={accounts[currentIndex]} />
<View style={styles.linkContainer}> <Stack direction="row" spacing={4}>
<View style={styles.signLink}> <TouchableOpacity
<TouchableOpacity onPress={() => {
onPress={() => { navigation.navigate("SignMessage", {
navigation.navigate('SignMessage', { selectedNamespace: selectedNetwork!.namespace,
selectedNamespace: selectedNetwork!.namespace, selectedChainId: selectedNetwork!.chainId,
selectedChainId: selectedNetwork!.chainId, accountInfo: accounts[currentIndex],
accountInfo: accounts[currentIndex], });
}); }}
}}> >
<Text <Link>Sign Message</Link>
variant="titleSmall" </TouchableOpacity>
style={[styles.hyperlink, { color: theme.colors.primary }]}>
Sign Message
</Text>
</TouchableOpacity>
</View>
<View style={styles.signLink}> <TouchableOpacity
<TouchableOpacity onPress={() => {
onPress={() => { navigation.navigate("AddNetwork");
navigation.navigate('AddNetwork'); }}
}}> >
<Text <Link>Add Network</Link>
variant="titleSmall" </TouchableOpacity>
style={[styles.hyperlink, { color: theme.colors.primary }]}>
Add Network
</Text>
</TouchableOpacity>
</View>
<View style={styles.signLink}> <TouchableOpacity
<TouchableOpacity onPress={() => {
onPress={() => { navigation.navigate("EditNetwork", {
navigation.navigate('EditNetwork', { selectedNetwork: selectedNetwork!,
selectedNetwork: selectedNetwork!, });
}); }}
}}> >
<Text <Link>Edit Network</Link>
variant="titleSmall" </TouchableOpacity>
style={[styles.hyperlink, { color: theme.colors.primary }]}>
Edit Network
</Text>
</TouchableOpacity>
</View>
{!selectedNetwork!.isDefault && ( {!selectedNetwork!.isDefault && (
<View style={styles.signLink}> <TouchableOpacity
<TouchableOpacity onPress={() => {
onPress={() => { setDeleteNetworkDialog(true);
setDeleteNetworkDialog(true); }}
}}> >
<Text <Link>Delete Network</Link>
variant="titleSmall" </TouchableOpacity>
style={[styles.hyperlink, { color: theme.colors.primary }]}>
Delete Network
</Text>
</TouchableOpacity>
</View>
)} )}
<ConfirmDialog <ConfirmDialog
title="Delete Network" title="Delete Network"
@ -221,7 +201,7 @@ const Accounts = () => {
onConfirm={handleRemove} onConfirm={handleRemove}
/> />
<ShowPKDialog /> <ShowPKDialog />
</View> </Stack>
</View> </View>
</View> </View>
); );

55
src/components/Dialog.tsx Normal file
View File

@ -0,0 +1,55 @@
import React from "react";
import {
Dialog,
DialogActions,
DialogContent,
DialogTitle,
Button,
Typography,
} from "@mui/material";
import styles from "../styles/stylesheet";
import GridView from "./Grid";
import { CustomDialogProps } from "../types";
const DialogComponent = ({
visible,
hideDialog,
contentText,
}: CustomDialogProps) => {
const words = contentText.split(" ");
const copyMnemonic = () => {
navigator.clipboard.writeText(contentText);
};
return (
<Dialog open={visible} onClose={hideDialog}>
<DialogTitle>Mnemonic</DialogTitle>
<DialogContent>
<Typography
variant="h6"
component="div"
style={{ color: "rgba(0, 0, 0, 0.87)" }}
>
Your mnemonic provides full access to your wallet and funds. Make sure
to note it down.
</Typography>
<Typography
variant="h6"
component="div"
style={{ ...styles.dialogWarning }}
>
Do not share your mnemonic with anyone
</Typography>
<GridView words={words} />
</DialogContent>
<DialogActions>
<Button onClick={copyMnemonic}>Copy</Button>
<Button onClick={hideDialog}>Done</Button>
</DialogActions>
</Dialog>
);
};
export { DialogComponent };

View File

@ -1,16 +1,16 @@
import React, { useState } from 'react'; import React, { useState } from "react";
import { TouchableOpacity, View } from 'react-native'; import { TouchableOpacity, View } from "react-native";
import { Button, Typography } from '@mui/material'; import { Button, Link, Typography } from "@mui/material";
import Dialog from '@mui/material/Dialog'; import Dialog from "@mui/material/Dialog";
import DialogTitle from '@mui/material/DialogTitle'; import DialogTitle from "@mui/material/DialogTitle";
import DialogContent from '@mui/material/DialogContent'; import DialogContent from "@mui/material/DialogContent";
import DialogActions from '@mui/material/DialogActions'; import DialogActions from "@mui/material/DialogActions";
import styles from '../styles/stylesheet'; import styles from "../styles/stylesheet";
import { getPathKey } from '../utils/misc'; import { getPathKey } from "../utils/misc";
import { useNetworks } from '../context/NetworksContext'; import { useNetworks } from "../context/NetworksContext";
import { useAccounts } from '../context/AccountsContext'; import { useAccounts } from "../context/AccountsContext";
import { Text, useTheme } from 'react-native-paper'; import { Text, useTheme } from "react-native-paper";
const ShowPKDialog = () => { const ShowPKDialog = () => {
const { currentIndex } = useAccounts(); const { currentIndex } = useAccounts();
@ -41,12 +41,9 @@ const ShowPKDialog = () => {
<TouchableOpacity <TouchableOpacity
onPress={() => { onPress={() => {
setShowPKDialog(true); setShowPKDialog(true);
}}> }}
<Text >
variant="titleSmall" <Link>Show Private Key</Link>
style={[styles.hyperlink, { color: theme.colors.primary }]}>
Show Private Key
</Text>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
<View> <View>
@ -66,8 +63,8 @@ const ShowPKDialog = () => {
variant="body1" variant="body1"
style={styles.dataBoxData} style={styles.dataBoxData}
sx={{ sx={{
wordWrap: 'break-word', wordWrap: "break-word",
whiteSpace: 'initial', whiteSpace: "initial",
}} }}
> >
{privateKey} {privateKey}
@ -76,11 +73,9 @@ const ShowPKDialog = () => {
)} )}
<View> <View>
<Typography variant="body1" style={styles.dialogWarning}> <Typography variant="body1" style={styles.dialogWarning}>
<Typography component="span"> <Typography component="span">Warning:</Typography>
Warning: Never disclose this key. Anyone with your private keys can steal
</Typography> any assets held in your account.
Never disclose this key. Anyone with your private keys can
steal any assets held in your account.
</Typography> </Typography>
</View> </View>
</DialogContent> </DialogContent>

View File

@ -36,12 +36,41 @@ const navigationTheme: typeof DarkTheme = {
card: "#18181A", card: "#18181A",
}, },
}; };
const muiTheme = createTheme({ const muiTheme = createTheme({
components: {
MuiButton: {
defaultProps: {
color: "primary",
sx: {
fontFamily: `DM Mono, monospace`,
fontWeight: 400,
},
},
},
MuiLink: {
defaultProps: {
color: "text.primary",
fontSize: "14px",
},
},
MuiTypography: {
defaultProps: {
fontWeight: 400,
},
},
},
palette: { palette: {
mode: "dark", mode: "dark",
primary: { primary: {
main: "#0000F4", main: "#0000F4",
}, },
secondary: {
main: "#A2A2FF",
},
error: {
main: "#B20710",
},
}, },
}); });

View File

@ -1,31 +1,30 @@
import React, { useCallback, useEffect, useState } from 'react'; import React, { useCallback, useEffect, useState } from "react";
import { View, ActivityIndicator, Image } from 'react-native'; import { View, ActivityIndicator, Image } from "react-native";
import { Button, Text } from 'react-native-paper'; import { Text } from "react-native-paper";
import { Box, Button, Divider, Portal, Snackbar } from "@mui/material";
import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { NativeStackNavigationProp } from "@react-navigation/native-stack";
import { useNavigation } from '@react-navigation/native'; import { useNavigation } from "@react-navigation/native";
import { getSdkError } from '@walletconnect/utils'; import { getSdkError } from "@walletconnect/utils";
import { Portal, Snackbar } from '@mui/material';
import { createWallet, resetWallet, retrieveAccounts } from '../utils/accounts'; import { createWallet, resetWallet, retrieveAccounts } from "../utils/accounts";
import { MnemonicDialog } from '../components/MnemonicDialog'; import { NetworkDropdown } from "../components/NetworkDropdown";
import ImportWalletDialog from '../components/ImportWalletDialog'; import Accounts from "../components/Accounts";
import { NetworkDropdown } from '../components/NetworkDropdown'; import CreateWallet from "../components/CreateWallet";
import Accounts from '../components/Accounts'; import ConfirmDialog from "../components/ConfirmDialog";
import CreateWallet from '../components/CreateWallet'; import styles from "../styles/stylesheet";
import ConfirmDialog from '../components/ConfirmDialog'; import { useAccounts } from "../context/AccountsContext";
import styles from '../styles/stylesheet'; import { useWalletConnect } from "../context/WalletConnectContext";
import { useAccounts } from '../context/AccountsContext'; import { NetworksDataState, StackParamsList } from "../types";
import { useWalletConnect } from '../context/WalletConnectContext'; import { useNetworks } from "../context/NetworksContext";
import { NetworksDataState, StackParamsList } from '../types'; import ImportWalletDialog from "../components/ImportWalletDialog";
import { useNetworks } from '../context/NetworksContext'; import { MnemonicDialog } from "../components/MnemonicDialog";
import { IS_IMPORT_WALLET_ENABLED } from '../utils/constants';
const WCLogo = () => { const WCLogo = () => {
return ( return (
<Image <Image
style={styles.walletConnectLogo} style={styles.walletConnectLogo}
source={require('../assets/WalletConnect-Icon-Blueberry.png')} source={require("../assets/WalletConnect-Icon-Blueberry.png")}
/> />
); );
}; };
@ -44,7 +43,7 @@ const HomeScreen = () => {
navigation.setOptions({ navigation.setOptions({
// eslint-disable-next-line react/no-unstable-nested-components // eslint-disable-next-line react/no-unstable-nested-components
headerRight: () => ( headerRight: () => (
<Button onPress={() => navigation.navigate('WalletConnect')}> <Button onClick={() => navigation.navigate("WalletConnect")}>
{<WCLogo />} {<WCLogo />}
</Button> </Button>
), ),
@ -62,9 +61,9 @@ const HomeScreen = () => {
const [mnemonicDialog, setMnemonicDialog] = useState<boolean>(false); const [mnemonicDialog, setMnemonicDialog] = useState<boolean>(false);
const [resetWalletDialog, setResetWalletDialog] = useState<boolean>(false); const [resetWalletDialog, setResetWalletDialog] = useState<boolean>(false);
const [toastVisible, setToastVisible] = useState(false); const [toastVisible, setToastVisible] = useState(false);
const [invalidMnemonicError, setInvalidMnemonicError] = useState(''); const [invalidMnemonicError, setInvalidMnemonicError] = useState("");
const [isAccountsFetched, setIsAccountsFetched] = useState<boolean>(true); const [isAccountsFetched, setIsAccountsFetched] = useState<boolean>(true);
const [phrase, setPhrase] = useState(''); const [phrase, setPhrase] = useState("");
const hideMnemonicDialog = () => setMnemonicDialog(false); const hideMnemonicDialog = () => setMnemonicDialog(false);
const hideResetDialog = () => setResetWalletDialog(false); const hideResetDialog = () => setResetWalletDialog(false);
@ -96,7 +95,7 @@ const HomeScreen = () => {
}; };
const importWalletHandler = async (recoveryPhrase: string) => { const importWalletHandler = async (recoveryPhrase: string) => {
try{ try {
const mnemonic = await createWallet(networksData, recoveryPhrase); const mnemonic = await createWallet(networksData, recoveryPhrase);
if (mnemonic) { if (mnemonic) {
fetchAccounts(); fetchAccounts();
@ -120,10 +119,10 @@ const HomeScreen = () => {
await resetWallet(); await resetWallet();
const sessions = web3wallet!.getActiveSessions(); const sessions = web3wallet!.getActiveSessions();
Object.keys(sessions).forEach(async sessionId => { Object.keys(sessions).forEach(async (sessionId) => {
await web3wallet!.disconnectSession({ await web3wallet!.disconnectSession({
topic: sessionId, topic: sessionId,
reason: getSdkError('USER_DISCONNECTED'), reason: getSdkError("USER_DISCONNECTED"),
}); });
}); });
setActiveSessions({}); setActiveSessions({});
@ -135,7 +134,7 @@ const HomeScreen = () => {
setCurrentIndex, setCurrentIndex,
setNetworksData, setNetworksData,
setSelectedNetwork, setSelectedNetwork,
web3wallet web3wallet,
]); ]);
const updateNetwork = (networkData: NetworksDataState) => { const updateNetwork = (networkData: NetworksDataState) => {
@ -149,70 +148,72 @@ const HomeScreen = () => {
return ( return (
<View style={styles.appContainer}> <View style={styles.appContainer}>
{!isAccountsFetched ? ( <Box sx={{ maxWidth: "752px", marginX: "auto" }}>
<View style={styles.spinnerContainer}> {!isAccountsFetched ? (
<Text style={styles.LoadingText}>Loading...</Text> <View style={styles.spinnerContainer}>
<ActivityIndicator size="large" color="#0000ff" /> <Text style={styles.LoadingText}>Loading...</Text>
</View> <ActivityIndicator size="large" color="#0000ff" />
) : isWalletCreated && selectedNetwork ? (
<>
<NetworkDropdown updateNetwork={updateNetwork} />
<View style={styles.accountComponent}>
<Accounts />
</View> </View>
<View style={styles.resetContainer}> ) : isWalletCreated && selectedNetwork ? (
<>
<NetworkDropdown updateNetwork={updateNetwork} />
<View style={styles.accountComponent}>
<Accounts />
</View>
<Divider flexItem sx={{ my: 4 }} />
<Button <Button
style={styles.resetButton} variant="contained"
mode="contained" onClick={() => {
buttonColor="#B82B0D"
onPress={() => {
setResetWalletDialog(true); setResetWalletDialog(true);
}}> }}
color="error"
>
Reset Wallet Reset Wallet
</Button> </Button>
</View> </>
</> ) : (
) : ( <>
<> <CreateWallet
<CreateWallet isWalletCreating={isWalletCreating}
isWalletCreating={isWalletCreating} createWalletHandler={createWalletHandler}
createWalletHandler={createWalletHandler} />
/> <View style={styles.createWalletContainer}>
{ IS_IMPORT_WALLET_ENABLED && <View style={styles.createWalletContainer}> <Button
<Button variant="contained"
mode="contained" onClick={() => setImportWalletDialog(true)}
onPress={() => setImportWalletDialog(true)}> >
Import Wallet Import Wallet
</Button> </Button>
</View> } </View>
</> </>
)} )}
<ImportWalletDialog <ImportWalletDialog
visible={importWalletDialog} visible={importWalletDialog}
hideDialog={() => setImportWalletDialog(false)} hideDialog={() => setImportWalletDialog(false)}
importWalletHandler={importWalletHandler} importWalletHandler={importWalletHandler}
/>
<MnemonicDialog
visible={mnemonicDialog}
hideDialog={hideMnemonicDialog}
contentText={phrase}
/>
<ConfirmDialog
title="Reset wallet"
visible={resetWalletDialog}
hideDialog={hideResetDialog}
onConfirm={confirmResetWallet}
/>
<Portal>
<Snackbar
open={toastVisible}
autoHideDuration={3000}
message={invalidMnemonicError}
onClose={() => setToastVisible(false)}
anchorOrigin={{ horizontal: 'center', vertical: 'bottom' }}
ContentProps={{ style: { backgroundColor: 'red', color: 'white'} }}
/> />
</Portal> <MnemonicDialog
visible={mnemonicDialog}
hideDialog={hideMnemonicDialog}
contentText={phrase}
/>
<ConfirmDialog
title="Reset wallet"
visible={resetWalletDialog}
hideDialog={hideResetDialog}
onConfirm={confirmResetWallet}
/>
<Portal>
<Snackbar
open={toastVisible}
autoHideDuration={3000}
message={invalidMnemonicError}
onClose={() => setToastVisible(false)}
anchorOrigin={{ horizontal: "center", vertical: "bottom" }}
ContentProps={{ style: { backgroundColor: "red", color: "white" } }}
/>
</Portal>
</Box>
</View> </View>
); );
}; };

131
yarn.lock
View File

@ -2125,6 +2125,33 @@
"@ethersproject/properties" "^5.7.0" "@ethersproject/properties" "^5.7.0"
"@ethersproject/strings" "^5.7.0" "@ethersproject/strings" "^5.7.0"
"@floating-ui/core@^1.6.0":
version "1.6.7"
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.7.tgz#7602367795a390ff0662efd1c7ae8ca74e75fb12"
integrity sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g==
dependencies:
"@floating-ui/utils" "^0.2.7"
"@floating-ui/dom@^1.0.0":
version "1.6.10"
resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.10.tgz#b74c32f34a50336c86dcf1f1c845cf3a39e26d6f"
integrity sha512-fskgCFv8J8OamCmyun8MfjB1Olfn+uZKjOKZ0vhYF3gRmEUXcGOjxWL8bBr7i4kIuPZ2KD2S3EUIOxnjC8kl2A==
dependencies:
"@floating-ui/core" "^1.6.0"
"@floating-ui/utils" "^0.2.7"
"@floating-ui/react-dom@^2.0.8":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.1.tgz#cca58b6b04fc92b4c39288252e285e0422291fb0"
integrity sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==
dependencies:
"@floating-ui/dom" "^1.0.0"
"@floating-ui/utils@^0.2.7":
version "0.2.7"
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.7.tgz#d0ece53ce99ab5a8e37ebdfe5e32452a2bfc073e"
integrity sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==
"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0": "@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0":
version "9.3.0" version "9.3.0"
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb"
@ -2557,11 +2584,37 @@
tweetnacl "^1.0.3" tweetnacl "^1.0.3"
tweetnacl-util "^0.15.1" tweetnacl-util "^0.15.1"
"@mui/base@5.0.0-beta.40":
version "5.0.0-beta.40"
resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-beta.40.tgz#1f8a782f1fbf3f84a961e954c8176b187de3dae2"
integrity sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==
dependencies:
"@babel/runtime" "^7.23.9"
"@floating-ui/react-dom" "^2.0.8"
"@mui/types" "^7.2.14"
"@mui/utils" "^5.15.14"
"@popperjs/core" "^2.11.8"
clsx "^2.1.0"
prop-types "^15.8.1"
"@mui/core-downloads-tracker@^5.16.4": "@mui/core-downloads-tracker@^5.16.4":
version "5.16.4" version "5.16.4"
resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.4.tgz#a34de72acd7e81fdbcc7eeb07786205e90dda148" resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.4.tgz#a34de72acd7e81fdbcc7eeb07786205e90dda148"
integrity sha512-rNdHXhclwjEZnK+//3SR43YRx0VtjdHnUFhMSGYmAMJve+KiwEja/41EYh8V3pZKqF2geKyfcFUenTfDTYUR4w== integrity sha512-rNdHXhclwjEZnK+//3SR43YRx0VtjdHnUFhMSGYmAMJve+KiwEja/41EYh8V3pZKqF2geKyfcFUenTfDTYUR4w==
"@mui/lab@^5.0.0-alpha.173":
version "5.0.0-alpha.173"
resolved "https://registry.yarnpkg.com/@mui/lab/-/lab-5.0.0-alpha.173.tgz#a0f9696d93a765b48d69a7da5aaca0affa510ae8"
integrity sha512-Gt5zopIWwxDgGy/MXcp6GueD84xFFugFai4hYiXY0zowJpTVnIrTQCQXV004Q7rejJ7aaCntX9hpPJqCrioshA==
dependencies:
"@babel/runtime" "^7.23.9"
"@mui/base" "5.0.0-beta.40"
"@mui/system" "^5.16.5"
"@mui/types" "^7.2.15"
"@mui/utils" "^5.16.5"
clsx "^2.1.0"
prop-types "^15.8.1"
"@mui/material@^5.16.4": "@mui/material@^5.16.4":
version "5.16.4" version "5.16.4"
resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.16.4.tgz#992d630637d9d38620e4937fb11d0a97965fdabf" resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.16.4.tgz#992d630637d9d38620e4937fb11d0a97965fdabf"
@ -2589,6 +2642,15 @@
"@mui/utils" "^5.16.4" "@mui/utils" "^5.16.4"
prop-types "^15.8.1" prop-types "^15.8.1"
"@mui/private-theming@^5.16.6":
version "5.16.6"
resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.16.6.tgz#547671e7ae3f86b68d1289a0b90af04dfcc1c8c9"
integrity sha512-rAk+Rh8Clg7Cd7shZhyt2HGTTE5wYKNSJ5sspf28Fqm/PZ69Er9o6KX25g03/FG2dfpg5GCwZh/xOojiTfm3hw==
dependencies:
"@babel/runtime" "^7.23.9"
"@mui/utils" "^5.16.6"
prop-types "^15.8.1"
"@mui/styled-engine@^5.16.4": "@mui/styled-engine@^5.16.4":
version "5.16.4" version "5.16.4"
resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.16.4.tgz#a7a8c9079c307bab91ccd65ed5dd1496ddf2a3ab" resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.16.4.tgz#a7a8c9079c307bab91ccd65ed5dd1496ddf2a3ab"
@ -2599,6 +2661,16 @@
csstype "^3.1.3" csstype "^3.1.3"
prop-types "^15.8.1" prop-types "^15.8.1"
"@mui/styled-engine@^5.16.6":
version "5.16.6"
resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.16.6.tgz#60110c106dd482dfdb7e2aa94fd6490a0a3f8852"
integrity sha512-zaThmS67ZmtHSWToTiHslbI8jwrmITcN93LQaR2lKArbvS7Z3iLkwRoiikNWutx9MBs8Q6okKvbZq1RQYB3v7g==
dependencies:
"@babel/runtime" "^7.23.9"
"@emotion/cache" "^11.11.0"
csstype "^3.1.3"
prop-types "^15.8.1"
"@mui/system@^5.16.4": "@mui/system@^5.16.4":
version "5.16.4" version "5.16.4"
resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.16.4.tgz#c03f971ed273f0ad06c69c949c05e866ad211407" resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.16.4.tgz#c03f971ed273f0ad06c69c949c05e866ad211407"
@ -2613,11 +2685,37 @@
csstype "^3.1.3" csstype "^3.1.3"
prop-types "^15.8.1" prop-types "^15.8.1"
"@mui/types@^7.2.15": "@mui/system@^5.16.5":
version "5.16.7"
resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.16.7.tgz#4583ca5bf3b38942e02c15a1e622ba869ac51393"
integrity sha512-Jncvs/r/d/itkxh7O7opOunTqbbSSzMTHzZkNLM+FjAOg+cYAZHrPDlYe1ZGKUYORwwb2XexlWnpZp0kZ4AHuA==
dependencies:
"@babel/runtime" "^7.23.9"
"@mui/private-theming" "^5.16.6"
"@mui/styled-engine" "^5.16.6"
"@mui/types" "^7.2.15"
"@mui/utils" "^5.16.6"
clsx "^2.1.0"
csstype "^3.1.3"
prop-types "^15.8.1"
"@mui/types@^7.2.14", "@mui/types@^7.2.15":
version "7.2.15" version "7.2.15"
resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.15.tgz#dadd232fe9a70be0d526630675dff3b110f30b53" resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.15.tgz#dadd232fe9a70be0d526630675dff3b110f30b53"
integrity sha512-nbo7yPhtKJkdf9kcVOF8JZHPZTmqXjJ/tI0bdWgHg5tp9AnIN4Y7f7wm9T+0SyGYJk76+GYZ8Q5XaTYAsUHN0Q== integrity sha512-nbo7yPhtKJkdf9kcVOF8JZHPZTmqXjJ/tI0bdWgHg5tp9AnIN4Y7f7wm9T+0SyGYJk76+GYZ8Q5XaTYAsUHN0Q==
"@mui/utils@^5.15.14", "@mui/utils@^5.16.5", "@mui/utils@^5.16.6":
version "5.16.6"
resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.16.6.tgz#905875bbc58d3dcc24531c3314a6807aba22a711"
integrity sha512-tWiQqlhxAt3KENNiSRL+DIn9H5xNVK6Jjf70x3PnfQPz1MPBdh7yyIcAyVBT9xiw7hP3SomRhPR7hzBMBCjqEA==
dependencies:
"@babel/runtime" "^7.23.9"
"@mui/types" "^7.2.15"
"@types/prop-types" "^15.7.12"
clsx "^2.1.1"
prop-types "^15.8.1"
react-is "^18.3.1"
"@mui/utils@^5.16.4": "@mui/utils@^5.16.4":
version "5.16.4" version "5.16.4"
resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.16.4.tgz#8e50e27a630e3d8eeb3e9d3bc31cbb0e4956f5fd" resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.16.4.tgz#8e50e27a630e3d8eeb3e9d3bc31cbb0e4956f5fd"
@ -13225,16 +13323,7 @@ string-natural-compare@^3.0.1:
resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4"
integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==
"string-width-cjs@npm:string-width@^4.2.0": "string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3" version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@ -13337,7 +13426,7 @@ stringify-object@^3.3.0:
is-obj "^1.0.1" is-obj "^1.0.1"
is-regexp "^1.0.0" is-regexp "^1.0.0"
"strip-ansi-cjs@npm:strip-ansi@^6.0.1": "strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1" version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@ -13351,13 +13440,6 @@ strip-ansi@^5.0.0, strip-ansi@^5.2.0:
dependencies: dependencies:
ansi-regex "^4.1.0" ansi-regex "^4.1.0"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
strip-ansi@^7.0.1: strip-ansi@^7.0.1:
version "7.1.0" version "7.1.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
@ -14654,7 +14736,7 @@ workbox-window@6.6.1:
"@types/trusted-types" "^2.0.2" "@types/trusted-types" "^2.0.2"
workbox-core "6.6.1" workbox-core "6.6.1"
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
version "7.0.0" version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@ -14672,15 +14754,6 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0" string-width "^4.1.0"
strip-ansi "^6.0.0" strip-ansi "^6.0.0"
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^8.1.0: wrap-ansi@^8.1.0:
version "8.1.0" version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"