mirror of
https://github.com/Chia-Network/chia-blockchain.git
synced 2026-09-24 07:25:03 -05:00
added new wallet and fixed loading
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"eslintConfig": {
|
||||
"extends": ["react-app", "shared-config"],
|
||||
"rules": {
|
||||
"additional-rule": "warn"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["**/*.ts?(x)"],
|
||||
"rules": {
|
||||
"additional-typescript-only-rule": "warn"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@
|
||||
"react-redux": "^7.2.1",
|
||||
"react-router": "^5.2.0",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"react-use": "^15.3.4",
|
||||
"redux": "^4.0.5",
|
||||
"redux-thunk": "^2.3.0",
|
||||
"stringify": "^5.2.0",
|
||||
|
||||
@@ -3,7 +3,7 @@ import { CssBaseline } from "@material-ui/core";
|
||||
import { Provider } from "react-redux";
|
||||
import { ModalDialog, Spinner } from '../pages/ModalDialog';
|
||||
import Router from './Router';
|
||||
import theme from '../theme/default';
|
||||
import theme from '../theme/light';
|
||||
import WebSocketConnection from "../hocs/WebsocketConnection";
|
||||
import { daemon_rpc_ws } from "../util/config";
|
||||
import store from "../modules/store";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { HashRouter, Switch, Route } from 'react-router-dom';
|
||||
import SelectKey from "./selectKey/SelectKey";
|
||||
import NewWallet from "../pages/NewWallet";
|
||||
import NewWallet from "./newWallet/NewWallet";
|
||||
import OldWallet from "../pages/OldWallet";
|
||||
import Dashboard from "../pages/Dashboard";
|
||||
import { RestoreBackup } from "../pages/backup/restoreBackup";
|
||||
@@ -41,9 +41,12 @@ export default function Router() {
|
||||
return (
|
||||
<HashRouter>
|
||||
<Switch>
|
||||
<Route path="/">
|
||||
<Route path="/" exact>
|
||||
<SelectKey />
|
||||
</Route>
|
||||
<Route path="/wallet">
|
||||
<NewWallet />
|
||||
</Route>
|
||||
</Switch>
|
||||
</HashRouter>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import styled from "styled-components";
|
||||
import { TextField } from "@material-ui/core";
|
||||
|
||||
export default styled(TextField)`
|
||||
color: #ffffff;
|
||||
|
||||
& .MuiFormLabel-root {
|
||||
color: #e3f2fd;
|
||||
}
|
||||
|
||||
& .MuiInputLabel-root {
|
||||
color: #e3f2fd;
|
||||
}
|
||||
|
||||
& label.Mui-focused {
|
||||
color: #e3f2fd;
|
||||
}
|
||||
|
||||
& label.Mui-required {
|
||||
color: #e3f2fd;
|
||||
}
|
||||
|
||||
& label.Mui-disabled {
|
||||
color: #e3f2fd;
|
||||
}
|
||||
|
||||
& label.Mui-root {
|
||||
color: #e3f2fd;
|
||||
}
|
||||
|
||||
& .MuiInput-underline:after {
|
||||
border-bottom-color: #e3f2fd;
|
||||
}
|
||||
|
||||
& .MuiOutlinedInput-root {
|
||||
& fieldset {
|
||||
border-color: #e3f2fd;
|
||||
}
|
||||
&:hover fieldset {
|
||||
border-color: #e3f2fd;
|
||||
}
|
||||
&.Mui-focused fieldset {
|
||||
border-color: #e3f2fd;
|
||||
}
|
||||
&.Mui-disabled fieldset {
|
||||
border-color: #e3f2fd;
|
||||
}
|
||||
}
|
||||
|
||||
& .MuiOutlinedInput-input {
|
||||
color: #ffffff;
|
||||
}
|
||||
`;
|
||||
@@ -0,0 +1,6 @@
|
||||
import { CircularProgress } from '@material-ui/core';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export default styled(CircularProgress)`
|
||||
color: white;
|
||||
`;
|
||||
@@ -1,11 +1,8 @@
|
||||
import React, { ReactNode } from 'react';
|
||||
import { CircularProgress, Typography } from '@material-ui/core';
|
||||
import { Typography } from '@material-ui/core';
|
||||
import styled from 'styled-components';
|
||||
import LayoutHero from '../layout/LayoutHero';
|
||||
|
||||
const StyledCircularProgress = styled(CircularProgress)`
|
||||
color: white;
|
||||
`;
|
||||
import Loading from './Loading';
|
||||
|
||||
const StyledTypography = styled(Typography)`
|
||||
color: white;
|
||||
@@ -23,7 +20,7 @@ export default function LoadingScreen(props: Props) {
|
||||
<StyledTypography variant="h6">
|
||||
{children}
|
||||
</StyledTypography>
|
||||
<StyledCircularProgress />
|
||||
<Loading />
|
||||
</LayoutHero>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import React from 'react';
|
||||
import logo from "../../assets/img/chia_logo.svg";
|
||||
|
||||
export default function Logo() {
|
||||
return (
|
||||
<img src={logo} alt="Logo" />
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import React from "react";
|
||||
import { Typography, Button, Grid, Container } from "@material-ui/core";
|
||||
import { ArrowBackIos as ArrowBackIosIcon } from "@material-ui/icons";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
import { useEffectOnce } from 'react-use';
|
||||
import { genereate_mnemonics, add_new_key_action } from "../../modules/message";
|
||||
import TextField from "../form/TextField";
|
||||
import type { RootState } from "../../modules/rootReducer";
|
||||
import Logo from '../logo/Logo';
|
||||
import Flex from '../flex/Flex';
|
||||
import Loading from '../loading/Loading';
|
||||
import Link from '../router/Link';
|
||||
import LayoutHero from "../layout/LayoutHero";
|
||||
|
||||
const MnemonicField = (props: any) => {
|
||||
return (
|
||||
<Grid item xs={2}>
|
||||
<TextField
|
||||
variant="outlined"
|
||||
margin="normal"
|
||||
disabled
|
||||
fullWidth
|
||||
color="primary"
|
||||
id={props.id}
|
||||
label={props.index}
|
||||
name="email"
|
||||
autoComplete="email"
|
||||
autoFocus
|
||||
value={props.word}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
export default function NewWallet() {
|
||||
const dispatch = useDispatch();
|
||||
const words = useSelector((state: RootState) => state.wallet_state.mnemonic);
|
||||
|
||||
useEffectOnce(() => {
|
||||
const get_mnemonics = genereate_mnemonics();
|
||||
dispatch(get_mnemonics);
|
||||
});
|
||||
|
||||
function handleNext() {
|
||||
dispatch(add_new_key_action(words));
|
||||
}
|
||||
|
||||
return (
|
||||
<LayoutHero>
|
||||
<Container maxWidth="xl">
|
||||
<Link to="/">
|
||||
<ArrowBackIosIcon fontSize="large" color="secondary" />
|
||||
</Link>
|
||||
</Container>
|
||||
<Container maxWidth="lg">
|
||||
<Flex flexDirection="column" gap={3} alignItems="center">
|
||||
<Logo />
|
||||
<Typography variant="h4" component="h1" gutterBottom>
|
||||
New Wallet
|
||||
</Typography>
|
||||
<Typography variant="subtitle1" align="center">
|
||||
Welcome! The following words are used for your wallet backup.
|
||||
Without them, you will lose access to your wallet, keep them safe!
|
||||
Write down each word along with the order number next to them.
|
||||
(Order is important)
|
||||
</Typography>
|
||||
{!!words.length ? (
|
||||
<Grid container spacing={2}>
|
||||
{words.map((word, i) => (
|
||||
<MnemonicField key={i} word={word} id={"id_" + (i + 1)} index={i + 1} />
|
||||
))}
|
||||
</Grid>
|
||||
) : (
|
||||
<Loading />
|
||||
)}
|
||||
<Container maxWidth="xs">
|
||||
<Button
|
||||
onClick={handleNext}
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
fullWidth
|
||||
>
|
||||
Next
|
||||
</Button>
|
||||
</Container>
|
||||
</Flex>
|
||||
</Container>
|
||||
</LayoutHero>
|
||||
);
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
import React, { useState } from "react";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
import { Container, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, Tooltip, List, ListItem, ListItemText, IconButton } from "@material-ui/core";
|
||||
import { Card, Typography, Container, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, Tooltip, List, ListItem, ListItemText, IconButton } from "@material-ui/core";
|
||||
import ListItemSecondaryAction from "@material-ui/core/ListItemSecondaryAction";
|
||||
import { Delete as DeleteIcon, Visibility as VisibilityIcon } from "@material-ui/icons";
|
||||
import Button from '../button/Button';
|
||||
import { makeStyles } from "@material-ui/core/styles";
|
||||
import logo from "../../assets/img/chia_logo.svg";
|
||||
import LayoutHero from '../layout/LayoutHero';
|
||||
import Flex from '../flex/Flex';
|
||||
import Logo from '../logo/Logo';
|
||||
import {
|
||||
login_action,
|
||||
delete_key,
|
||||
@@ -21,15 +22,9 @@ import {
|
||||
presentNewWallet
|
||||
} from "../../modules/entranceMenu";
|
||||
import { resetMnemonic } from "../../modules/mnemonic";
|
||||
import { RootState } from "../../modules/rootReducer";
|
||||
import type { RootState } from "../../modules/rootReducer";
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
paper: {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
height: "100%"
|
||||
},
|
||||
centeredSpan: {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
@@ -38,29 +33,6 @@ const useStyles = makeStyles(theme => ({
|
||||
textField: {
|
||||
borderColor: "#ffffff"
|
||||
},
|
||||
topButton: {
|
||||
width: 400,
|
||||
height: 45,
|
||||
marginTop: theme.spacing(4),
|
||||
marginBottom: theme.spacing(1)
|
||||
},
|
||||
bottomButton: {
|
||||
width: 400,
|
||||
height: 45,
|
||||
marginTop: theme.spacing(2),
|
||||
marginBottom: theme.spacing(1)
|
||||
},
|
||||
bottomButtonRed: {
|
||||
width: 400,
|
||||
height: 45,
|
||||
marginTop: theme.spacing(2),
|
||||
marginBottom: theme.spacing(1),
|
||||
color: "red"
|
||||
},
|
||||
logo: {
|
||||
marginTop: theme.spacing(8),
|
||||
marginBottom: theme.spacing(3)
|
||||
},
|
||||
whiteText: {
|
||||
color: "white"
|
||||
},
|
||||
@@ -79,7 +51,7 @@ const useStyles = makeStyles(theme => ({
|
||||
export default function SelectKey() {
|
||||
const dispatch = useDispatch();
|
||||
const classes = useStyles();
|
||||
const public_key_fingerprints = useSelector(
|
||||
const publicKeyFingerprints = useSelector(
|
||||
(state: RootState) => state.wallet_state.public_key_fingerprints
|
||||
);
|
||||
|
||||
@@ -122,92 +94,100 @@ export default function SelectKey() {
|
||||
dispatch(changeEntranceMenu(presentNewWallet));
|
||||
};
|
||||
|
||||
const list_items = public_key_fingerprints.map(fingerprint => {
|
||||
return (
|
||||
<ListItem
|
||||
button
|
||||
onClick={handleClick(fingerprint)}
|
||||
key={fingerprint.toString()}
|
||||
>
|
||||
<ListItemText
|
||||
className={classes.rightPadding}
|
||||
primary={`Private key with public fingerprint ${fingerprint.toString()}`}
|
||||
secondary="Can be backed up to mnemonic seed"
|
||||
/>
|
||||
<ListItemSecondaryAction>
|
||||
<Tooltip title="See private key">
|
||||
<IconButton
|
||||
edge="end"
|
||||
aria-label="delete"
|
||||
onClick={showKey(fingerprint)}
|
||||
>
|
||||
<VisibilityIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="DANGER: permanantly delete private key">
|
||||
<IconButton
|
||||
edge="end"
|
||||
aria-label="delete"
|
||||
onClick={handleDelete(fingerprint)}
|
||||
>
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</ListItemSecondaryAction>
|
||||
</ListItem>
|
||||
);
|
||||
});
|
||||
const hasFingerprints = publicKeyFingerprints && !!publicKeyFingerprints.length;
|
||||
|
||||
return (
|
||||
<LayoutHero>
|
||||
<Container component="main" maxWidth="xs">
|
||||
<div className={classes.paper}>
|
||||
<img className={classes.logo} src={logo} alt="Logo" />
|
||||
{public_key_fingerprints && public_key_fingerprints.length > 0 ? (
|
||||
<Container maxWidth="xs">
|
||||
<Flex flexDirection="column" alignItems="center" gap={3}>
|
||||
<Logo />
|
||||
{hasFingerprints ? (
|
||||
<h1 className={classes.whiteText}>Select Key</h1>
|
||||
) : (
|
||||
<span className={classes.centeredSpan}>
|
||||
<h2 className={classes.whiteText}>Sign In</h2>
|
||||
<p className={classes.whiteP}>
|
||||
<>
|
||||
<Typography variant="h5" component="h1" color="primary" gutterBottom>
|
||||
Sign In
|
||||
</Typography>
|
||||
<Typography variant="subtitle1">
|
||||
Welcome to Chia. Please log in with an existing key, or create a
|
||||
a new key.
|
||||
</p>
|
||||
</span>
|
||||
</Typography>
|
||||
</>
|
||||
)}
|
||||
<div className={classes.demo}>
|
||||
<List>{list_items}</List>
|
||||
</div>
|
||||
<Link onClick={goToMnemonics} to="/mnemonics" fullWidth>
|
||||
<Flex flexDirection="column" gap={3} alignItems="stretch" alignSelf="stretch">
|
||||
{hasFingerprints && (
|
||||
<Card>
|
||||
<List>
|
||||
{publicKeyFingerprints.map((fingerprint) => (
|
||||
<ListItem
|
||||
button
|
||||
onClick={handleClick(fingerprint)}
|
||||
key={fingerprint.toString()}
|
||||
>
|
||||
<ListItemText
|
||||
className={classes.rightPadding}
|
||||
primary={`Private key with public fingerprint ${fingerprint.toString()}`}
|
||||
secondary="Can be backed up to mnemonic seed"
|
||||
/>
|
||||
<ListItemSecondaryAction>
|
||||
<Tooltip title="See private key">
|
||||
<IconButton
|
||||
edge="end"
|
||||
aria-label="delete"
|
||||
onClick={showKey(fingerprint)}
|
||||
>
|
||||
<VisibilityIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="DANGER: permanantly delete private key">
|
||||
<IconButton
|
||||
edge="end"
|
||||
aria-label="delete"
|
||||
onClick={handleDelete(fingerprint)}
|
||||
>
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</ListItemSecondaryAction>
|
||||
</ListItem>
|
||||
))}
|
||||
</List>
|
||||
</Card>
|
||||
)}
|
||||
<Link onClick={goToMnemonics} to="/mnemonics">
|
||||
<Button
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
size="large"
|
||||
fullWidth
|
||||
>
|
||||
Import from Mnemonics (24 words)
|
||||
</Button>
|
||||
</Link>
|
||||
<Link to="/wallet">
|
||||
<Button
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
size="large"
|
||||
fullWidth
|
||||
>
|
||||
Create a new private key
|
||||
</Button>
|
||||
</Link>
|
||||
<Button
|
||||
onClick={handleClickOpen}
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
color="danger"
|
||||
size="large"
|
||||
fullWidth
|
||||
>
|
||||
Import from Mnemonics (24 words)
|
||||
Delete all keys
|
||||
</Button>
|
||||
</Link>
|
||||
<Link onClick={goToNewWallet} to="/wallet" fullWidth>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
fullWidth
|
||||
>
|
||||
Create a new private key
|
||||
</Button>
|
||||
</Link>
|
||||
<Button
|
||||
onClick={handleClickOpen}
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="danger"
|
||||
fullWidth
|
||||
>
|
||||
Delete all keys
|
||||
</Button>
|
||||
</div>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Container>
|
||||
<Dialog
|
||||
open={open}
|
||||
|
||||
@@ -92,7 +92,11 @@ export default function incomingReducer(state = { ...initialState }, action: any
|
||||
const command = message.command;
|
||||
let success, wallets;
|
||||
if (command === "generate_mnemonic") {
|
||||
return { ...state, mnemonic: message.data.mnemonic };
|
||||
const mnemonic = typeof message.data.mnemonic === 'string'
|
||||
? message.data.mnemonic.split(' ')
|
||||
: message.data.mnemonic;
|
||||
|
||||
return { ...state, mnemonic };
|
||||
} else if (command === "add_key") {
|
||||
success = data.success;
|
||||
return { ...state, logged_in: success };
|
||||
@@ -165,7 +169,7 @@ export default function incomingReducer(state = { ...initialState }, action: any
|
||||
id = data.wallet_id;
|
||||
var transactions = data.transactions;
|
||||
wallets = state.wallets;
|
||||
wallet = wallets[parseInt(id)];
|
||||
wallet = wallets[Number(id)];
|
||||
if (!wallet) {
|
||||
return state;
|
||||
}
|
||||
@@ -176,7 +180,7 @@ export default function incomingReducer(state = { ...initialState }, action: any
|
||||
id = data.wallet_id;
|
||||
var address = data.address;
|
||||
wallets = state.wallets;
|
||||
wallet = wallets[parseInt(id)];
|
||||
wallet = wallets[Number(id)];
|
||||
if (!wallet) {
|
||||
return state;
|
||||
}
|
||||
@@ -212,7 +216,7 @@ export default function incomingReducer(state = { ...initialState }, action: any
|
||||
id = data.wallet_id;
|
||||
const colour = data.colour;
|
||||
wallets = state.wallets;
|
||||
wallet = wallets[parseInt(id)];
|
||||
wallet = wallets[Number(id)];
|
||||
if (!wallet) {
|
||||
return state;
|
||||
}
|
||||
@@ -222,7 +226,7 @@ export default function incomingReducer(state = { ...initialState }, action: any
|
||||
const id = data.wallet_id;
|
||||
const name = data.name;
|
||||
wallets = state.wallets;
|
||||
wallet = wallets[parseInt(id)];
|
||||
wallet = wallets[Number(id)];
|
||||
if (!wallet) {
|
||||
return state;
|
||||
}
|
||||
@@ -232,7 +236,7 @@ export default function incomingReducer(state = { ...initialState }, action: any
|
||||
if (command === "state_changed" && data.state === "tx_update") {
|
||||
const id = data.wallet_id;
|
||||
wallets = state.wallets;
|
||||
wallet = wallets[parseInt(id)];
|
||||
wallet = wallets[Number(id)];
|
||||
wallet.sending_transaction = false;
|
||||
wallet.send_transaction_result = message.data.additional_data;
|
||||
return { ...state };
|
||||
|
||||
@@ -6,8 +6,6 @@ export default {
|
||||
palette: {
|
||||
primary: {
|
||||
main: "#5DA962",
|
||||
light: 'white',
|
||||
dark: 'orange',
|
||||
contrastText: "#ffffff",
|
||||
},
|
||||
secondary: {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
type Program = {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
export default Program;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import WalletType from "./WalletType";
|
||||
import type Transaction from "./Transaction";
|
||||
import type WalletType from "./WalletType";
|
||||
|
||||
interface Wallet {
|
||||
id: number,
|
||||
@@ -10,7 +11,7 @@ interface Wallet {
|
||||
balance_spendable: number,
|
||||
balance_frozen: number,
|
||||
balance_change: number,
|
||||
transactions: [],
|
||||
transactions: Transaction[],
|
||||
address: string,
|
||||
colour: string,
|
||||
sending_transaction: boolean,
|
||||
|
||||
Reference in New Issue
Block a user