Skip to content

Commit

Permalink
Merge pull request anoma#55 from heliaxdev/feat/36-redux-and-other-ui…
Browse files Browse the repository at this point in the history
…-improvements

feat/36 - Clean up Account Creation
  • Loading branch information
jurevans authored May 20, 2022
2 parents 99c33d0 + deb4d97 commit 25069e3
Show file tree
Hide file tree
Showing 10 changed files with 212 additions and 243 deletions.
128 changes: 54 additions & 74 deletions packages/anoma-wallet/src/App/AccountCreation/AccountCreation.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { useState, useEffect, useContext } from "react";
import { Routes, Route, useNavigate, useLocation } from "react-router-dom";
import { Provider } from "react-redux";
import { AnimatePresence } from "framer-motion";
import { ThemeContext } from "styled-components";

import { TopLevelRoute } from "App/types";
import { AccountCreationRoute, accountCreationSteps } from "./types";
import { Session, Wallet } from "lib";
import { AppContext } from "App/App";
import { InitialAccount } from "slices/accounts";
import { AppStore } from "store/store";

import { Button } from "components/ButtonTemporary";
import { Icon, IconName } from "components/Icon";
Expand All @@ -27,6 +26,7 @@ import {
RouteContainer,
MotionContainer,
} from "./AccountCreation.components";
import { Session } from "lib";

type AnimatedTransitionProps = {
elementKey: string;
Expand Down Expand Up @@ -54,33 +54,21 @@ const AnimatedTransition = (props: AnimatedTransitionProps): JSX.Element => {
);
};

const createAccount = async (
alias: string,
mnemonic: string
): Promise<InitialAccount> => {
const tokenType = "NAM";
const wallet = await new Wallet(mnemonic, tokenType).init();
const account = wallet.new(0);
const { public: publicKey, secret: signingKey, wif: address } = account;

return {
alias,
tokenType,
address,
publicKey,
signingKey,
};
type Props = {
setStore: (password: string) => void;
setIsLoggedIn: () => void;
store: AppStore | undefined;
};

/**
* The main purpose of this is to coordinate the flow for creating a new account.
* it persist the data and coordinates the logic for animating the transitions
* between the screens in the flow.
*/
function AccountCreation(): JSX.Element {
const context = useContext(AppContext);
const { setIsLoggedIn, setInitialAccount } = context;

function AccountCreation({
setStore,
setIsLoggedIn,
store,
}: Props): JSX.Element {
// account details defaults
const defaultAccountCreationDetails: AccountCreationDetails = {
seedPhraseLength: "12",
Expand All @@ -94,6 +82,7 @@ function AccountCreation(): JSX.Element {
);
const [seedPhrase, setSeedPhrase] = useState<string[]>();
const [stepIndex, setStepIndex] = useState(0);

const themeContext = useContext(ThemeContext);
const navigate = useNavigate();

Expand Down Expand Up @@ -143,6 +132,15 @@ function AccountCreation(): JSX.Element {
navigate(`${accountCreationSteps[stepIndex - 1]}`);
};

// Establish login session and store mnemonic
const setSession = async (
mnemonic: string,
password: string
): Promise<Session> => {
const session = new Session().setSession(password);
return await session.setSeed(mnemonic);
};

return (
<AccountCreationContainer>
<TopSection>
Expand Down Expand Up @@ -199,6 +197,7 @@ function AccountCreation(): JSX.Element {
>
<AccountInformation
accountCreationDetails={accountCreationDetails}
setStore={setStore}
onSetAccountCreationDetails={(
accountCreationDetailsDelta
) => {
Expand Down Expand Up @@ -254,38 +253,12 @@ function AccountCreation(): JSX.Element {
>
<SeedPhraseConfirmation
seedPhrase={seedPhrase || []}
onConfirmSeedPhrase={() => {
onConfirmSeedPhrase={async () => {
await setSession(
(seedPhrase || [])?.join(" "),
accountCreationDetails.password || ""
);
navigateToNext();

const createSeed = async (): Promise<void> => {
// TODO
// likely best to move the key creation to the loading of
// the completion screen so that the user do not get the
// bad UX by seeing a noticeable delay
if (
accountCreationDetails.password &&
accountCreationDetails.accountName
) {
const mnemonic = seedPhrase?.join(" ") || "";
const account = await createAccount(
accountCreationDetails.accountName,
mnemonic
);

// Establish login session
const session = new Session();
session.setSession(accountCreationDetails.password);
await session.setSeed(mnemonic);

setInitialAccount && setInitialAccount(account);
} else {
alert(
"something is wrong with the master seed creation 🤨"
);
}
};

createSeed();
}}
onCtaHover={() => {
// read the need for this above the hook
Expand All @@ -295,25 +268,32 @@ function AccountCreation(): JSX.Element {
</AnimatedTransition>
}
/>
<Route
path={`/${AccountCreationRoute.Completion}`}
element={
<AnimatedTransition
elementKey={AccountCreationRoute.Completion}
animationFromRightToLeft={animationFromRightToLeft}
>
<Completion
onClickDone={() => {
navigate(TopLevelRoute.SettingsAccounts);
}}
onClickSeeAccounts={() => {
setIsLoggedIn && setIsLoggedIn();
navigate(TopLevelRoute.Wallet);
}}
/>
</AnimatedTransition>
}
/>
{store && (
<Route
path={`/${AccountCreationRoute.Completion}`}
element={
<AnimatedTransition
elementKey={AccountCreationRoute.Completion}
animationFromRightToLeft={animationFromRightToLeft}
>
<Provider store={store}>
<Completion
onClickDone={() => {
navigate(TopLevelRoute.SettingsAccounts);
}}
onClickSeeAccounts={() => {
setIsLoggedIn();
navigate(TopLevelRoute.Wallet);
}}
mnemonic={(seedPhrase || []).join(" ")}
alias={accountCreationDetails.accountName || ""}
password={accountCreationDetails.password || ""}
/>
</Provider>
</AnimatedTransition>
}
/>
)}
</Routes>
</AnimatePresence>
</RouteContainer>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useContext } from "react";
import React from "react";
import { Button } from "components/ButtonTemporary";
import {
AccountInformationViewContainer,
Expand All @@ -18,7 +18,6 @@ import {
RecoveryPhraseLengthRadioButtonsContainer,
RecoveryPhraseLengthContainer,
} from "./AccountInformation.components";
import { AppContext } from "App/App";

// this is being used:
// to store the data in the parent when editing
Expand All @@ -33,7 +32,7 @@ export type AccountCreationDetails = {
type AccountInformationViewProps = {
// if the user navigates back and forth this might be there
accountCreationDetails?: AccountCreationDetails;

setStore: (password: string) => void;
onSubmitAccountCreationDetails: (
accountCreationDetails: AccountCreationDetails
) => void;
Expand All @@ -50,13 +49,12 @@ const AccountInformation = (
props: AccountInformationViewProps
): React.ReactElement => {
const {
setStore,
onSubmitAccountCreationDetails,
onSetAccountCreationDetails,
onCtaHover,
accountCreationDetails,
} = props;
const context = useContext(AppContext) || {};
const { setPassword } = context;
// setting these default values if no data was passed
const { seedPhraseLength = "12", accountName = "" } =
accountCreationDetails || {};
Expand Down Expand Up @@ -143,9 +141,6 @@ const AccountInformation = (
onChange={(event) => {
const { value } = event.target;
setPassword1(value);
if (setPassword) {
setPassword(value);
}
}}
onFocus={() => {
setPassword1Feedback("");
Expand Down Expand Up @@ -199,6 +194,7 @@ const AccountInformation = (
...accountCreationDetails,
password: password1,
};
setStore && setStore(password1);
onSubmitAccountCreationDetails(accountCreationDetailsToSubmit);
}
}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { useContext, useEffect } from "react";
import { AppContext } from "App/App";
import { Button, Variant } from "components/ButtonTemporary";
import { Image, ImageName } from "components/Image";
import { Session } from "lib";
import { Wallet } from "lib";

import {
CompletionViewContainer,
Expand All @@ -14,22 +12,50 @@ import {
ButtonContainer,
} from "./Completion.components";

import { addAccount, InitialAccount } from "slices/accounts";
import { useEffect } from "react";
import { useAppDispatch } from "store";

type CompletionViewProps = {
// navigates to the account
onClickSeeAccounts: () => void;
// navigates to the settings
onClickDone: () => void;
mnemonic: string;
alias: string;
password: string;
};

const createAccount = async (
alias: string,
mnemonic: string
): Promise<InitialAccount> => {
const tokenType = "NAM";
const wallet = await new Wallet(mnemonic, tokenType).init();
const account = wallet.new(0);
const { public: publicKey, secret: signingKey, wif: address } = account;

return {
alias,
tokenType,
address,
publicKey,
signingKey,
};
};

const Completion = (props: CompletionViewProps): JSX.Element => {
const { onClickDone, onClickSeeAccounts } = props;
const context = useContext(AppContext) || {};
const { password = "" } = context;
const { onClickDone, onClickSeeAccounts, mnemonic, password, alias } = props;

const dispatch = useAppDispatch();

useEffect(() => {
// Log the user in:
new Session().setSession(password);
// eslint-disable-next-line react-hooks/exhaustive-deps
if (password) {
(async () => {
const account = await createAccount(alias, mnemonic);
dispatch(addAccount(account));
})();
}
}, []);

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import { useEffect, useState } from "react";
import { Button } from "components/ButtonTemporary";
import {
AccountInformationViewContainer,
Expand All @@ -24,13 +24,23 @@ function SeedPhraseConfirmation(
): JSX.Element {
const { seedPhrase, onCtaHover, onConfirmSeedPhrase } = props;
const seedPhraseLength = seedPhrase.length;
const [verificationInput, setVerificationInput] = React.useState("");
const [indexToConfirm, setIndexToConfirm] = React.useState(-1);
const [verificationInput, setVerificationInput] = useState("");
const [isSubmitting, setIsSubmitting] = useState(false);
const [indexToConfirm, setIndexToConfirm] = useState(-1);

React.useEffect(() => {
useEffect(() => {
setIndexToConfirm(Math.floor(Math.random() * seedPhraseLength));
}, []);

useEffect(() => {
if (isSubmitting) {
// Call after the time it takes to animate the button into a disabled state
setTimeout(() => {
onConfirmSeedPhrase();
}, 300);
}
}, [isSubmitting]);

return (
<AccountInformationViewContainer>
{/* header */}
Expand Down Expand Up @@ -58,12 +68,15 @@ function SeedPhraseConfirmation(
</InputContainer>
</DescriptionAndInputContainer>
{/* submit */}
{isSubmitting && <p>Creating master account...</p>}
<ButtonContainer>
<Button
onClick={() => {
onConfirmSeedPhrase();
setIsSubmitting(true);
}}
disabled={verificationInput !== seedPhrase[indexToConfirm]}
disabled={
verificationInput !== seedPhrase[indexToConfirm] || isSubmitting
}
onHover={onCtaHover}
>
Verify
Expand Down
Loading

0 comments on commit 25069e3

Please sign in to comment.