Skip to content

Commit

Permalink
Show mnemonic menu (#3259)
Browse files Browse the repository at this point in the history
### What

This PR implements flow of exporting mnemonics.
- adding menu option and slideup for exporting mnemonics
- handling both short and long mnemonics

Improvements:
- code cleanup and improvements
- fixing small visual bugs
- making export slideups bigger
- hiding unnecessary locked wallet snackbar

### Testing

- go through both flows - mnemonic export and private keys export 

### Known problems

- the blur over the mnemonic is buggy in chrome, part of the blur that
is not initially visible inside the viewport may not be blurred. Will be
resolved later.


![image](https://user-images.githubusercontent.com/20949277/230622272-2dc46f8a-37c4-48c5-9370-8bde36733fbf.png)![image](https://user-images.githubusercontent.com/20949277/230622371-b16f4383-164c-4ec2-89b3-48f42c80ca31.png)

Latest build:
[extension-builds-3259](https://github.com/tahowallet/extension/suites/12131636841/artifacts/639590688)
(as of Mon, 10 Apr 2023 12:54:22 GMT).
  • Loading branch information
kkosiorowska committed Apr 11, 2023
2 parents 223e5bc + a30279d commit 619111b
Show file tree
Hide file tree
Showing 19 changed files with 702 additions and 261 deletions.
6 changes: 4 additions & 2 deletions background/redux-slices/selectors/signingSelectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { RootState } from ".."
import { isDefined } from "../../lib/utils/type-guards"
import {
KeyringAccountSigner,
WalletAccountSigner,
PrivateKeyAccountSigner,
} from "../../services/keyring"
import { LedgerAccountSigner } from "../../services/ledger"
import { AccountSigner, ReadOnlyAccountSigner } from "../../services/signing"
Expand Down Expand Up @@ -71,7 +71,9 @@ export const selectAccountSignersByAddress = createSelector(

const privateKeyEntries = Object.entries(walletsByAddress)
.map(
([address, wallet]): [HexString, WalletAccountSigner] | undefined => {
([address, wallet]):
| [HexString, PrivateKeyAccountSigner]
| undefined => {
if (wallet.id === null) {
return undefined
}
Expand Down
2 changes: 1 addition & 1 deletion background/services/keyring/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export type KeyringAccountSigner = {
keyringID: string
}

export type WalletAccountSigner = {
export type PrivateKeyAccountSigner = {
type: "privateKey"
walletID: string
}
Expand Down
4 changes: 2 additions & 2 deletions background/services/signing/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { StatusCodes, TransportStatusError } from "@ledgerhq/errors"
import KeyringService, {
KeyringAccountSigner,
WalletAccountSigner,
PrivateKeyAccountSigner,
} from "../keyring"
import LedgerService, { LedgerAccountSigner } from "../ledger"
import {
Expand Down Expand Up @@ -56,7 +56,7 @@ export const ReadOnlyAccountSigner = { type: "read-only" } as const
*/
export type AccountSigner =
| typeof ReadOnlyAccountSigner
| WalletAccountSigner
| PrivateKeyAccountSigner
| KeyringAccountSigner
| HardwareAccountSigner
export type HardwareAccountSigner = LedgerAccountSigner
Expand Down
20 changes: 16 additions & 4 deletions ui/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,25 @@
"copySuccess": "Copied!"
},
"explainer": {
"header": "What is a private key",
"text1": "You need a recovery phrase in case you loose access to your computer, wallet or you forget your password.",
"text2": "Recovery phrase is the only way to regain access to your funds stored on those addresses.",
"text3": "Taho has the option to import or create multiple recovery phrases. If you have multiple, make sure that you have safely save and store them all."
"header": "What is a private key?",
"text1": "A private key is also known as a secret key is a string of letter and numbers that allow you to access and manage your assets on one address.",
"text2": "A private key only unlocks one address, while a recovery phrase unlocks all addresses that are tied to that phrase.",
"text3": "If you don’t use recovery phrase, you need to save a private key for each address."
}
},
"showMnemonic": {
"header": "Show Recovery Phrase",
"warningMessage": "Anybody that has your recovery phrase can move your assets.",
"mnemonicInfo": "Why do i need a recovery phrase?",
"exportingMnemonic": {
"confirmationDesc": "I understand that other Recovery Phrases, Ledger, Private Keys or Read-only accounts will not be saved with this recovery phrase.",
"invalidMessage": "Check the above box to confirm",
"showBtn": "Show recovery phrase",
"copyBtn": "Copy phrase to clipboard",
"copySuccess": "Copied!",
"address": "address",
"addresses": "addresses"
},
"explainer": {
"header": "Why do i need a recovery phrase?",
"text1": "You need a recovery phrase in case you loose access to your computer, wallet or you forget your password.",
Expand Down
4 changes: 3 additions & 1 deletion ui/components/AccountItem/AccountItemOptionsMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import SharedDropdown from "../Shared/SharedDropDown"
import SharedSlideUpMenu from "../Shared/SharedSlideUpMenu"
import AccountItemEditName from "./AccountItemEditName"
import AccountItemRemovalConfirm from "./AccountItemRemovalConfirm"
import ShowPrivateKey from "./ShowPrivateKey"
import ShowPrivateKey from "../AccountsBackup/ShowPrivateKey"

type AccountItemOptionsMenuProps = {
accountTotal: AccountTotal
Expand Down Expand Up @@ -97,6 +97,8 @@ export default function AccountItemOptionsMenu({
</SharedSlideUpMenu>
<SharedSlideUpMenu
isOpen={showPrivateKeyMenu}
size="custom"
customSize="580px"
close={(e) => {
e?.stopPropagation()
setShowPrivateKeyMenu(false)
Expand Down
232 changes: 0 additions & 232 deletions ui/components/AccountItem/ShowPrivateKey.tsx

This file was deleted.

61 changes: 61 additions & 0 deletions ui/components/AccountsBackup/ConfirmReveal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React, { ReactElement, useState } from "react"
import SharedButton from "../Shared/SharedButton"
import SharedCheckbox from "../Shared/SharedCheckbox"

export default function ConfirmReveal({
description,
invalidMessage,
confirmButton,
onConfirm,
}: {
description: string
invalidMessage: string
confirmButton: string
onConfirm: () => void
}): ReactElement {
const [showInvalidMessage, setShowInvalidMessage] = useState(false)
const [isConfirmed, setIsConfirmed] = useState(false)

return (
<>
<div className="confirmation_container">
<SharedCheckbox
label={description}
message={invalidMessage}
value={isConfirmed}
invalid={showInvalidMessage && !isConfirmed}
onChange={(value) => {
setIsConfirmed(value)
setShowInvalidMessage(false)
}}
/>
<div>
<SharedButton
type="primary"
size="medium"
isDisabled={!isConfirmed}
hideEvents={false}
onClick={() => {
if (isConfirmed) {
onConfirm()
} else {
setShowInvalidMessage(true)
}
}}
>
{confirmButton}
</SharedButton>
</div>
</div>
<style jsx>{`
.confirmation_container {
height: 175px;
display: flex;
flex-direction: column;
justify-content: space-between;
margin-top: 16px;
}
`}</style>
</>
)
}
Loading

0 comments on commit 619111b

Please sign in to comment.