mirror of
https://github.com/haveno-dex/haveno-ui.git
synced 2025-02-25 17:11:08 -05:00
feat: wallet seed phrase
--- Co-authored-by: @schowdhuri Reviewed-by: @schowdhuri
This commit is contained in:
parent
250d742d48
commit
ad493f5147
@ -0,0 +1,67 @@
|
||||
// =============================================================================
|
||||
// Copyright 2022 Haveno
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
import {
|
||||
createStyles,
|
||||
Group,
|
||||
List,
|
||||
ListItem,
|
||||
Space,
|
||||
Stack,
|
||||
} from "@mantine/core";
|
||||
import { BodyText } from "@atoms/Typography";
|
||||
import { useXmrSeed } from "@hooks/haveno/useXmrSeed";
|
||||
|
||||
export function SeedPhrase() {
|
||||
const { classes } = useStyles();
|
||||
const { data: xmrseeds, isLoading } = useXmrSeed();
|
||||
const seeds = xmrseeds?.split(" ");
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<Space h="lg" />
|
||||
{isLoading && <BodyText>Loading Wallet Seeds...</BodyText>}
|
||||
<List type="ordered" className={classes.container}>
|
||||
{seeds?.map((label, index) => (
|
||||
<Group key={index} className={classes.background} spacing="sm">
|
||||
<ListItem>{label}</ListItem>
|
||||
</Group>
|
||||
))}
|
||||
</List>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
const useStyles = createStyles((theme) => ({
|
||||
background: {
|
||||
backgroundColor: theme.colors.gray[3],
|
||||
borderRadius: "0.5rem",
|
||||
flex: "0 30%",
|
||||
li: {
|
||||
color: theme.colors.gray[6],
|
||||
},
|
||||
padding: "0.75rem 1rem",
|
||||
span: {
|
||||
color: theme.colors.gray[9],
|
||||
},
|
||||
width: "15rem",
|
||||
},
|
||||
container: {
|
||||
display: "flex",
|
||||
flexWrap: "wrap",
|
||||
gap: "1rem",
|
||||
},
|
||||
}));
|
@ -0,0 +1,30 @@
|
||||
// =============================================================================
|
||||
// Copyright 2022 Haveno
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
import type { ComponentStory, ComponentMeta } from "@storybook/react";
|
||||
import { WalletManagement } from ".";
|
||||
|
||||
export default {
|
||||
title: "organisms/Wallet Management",
|
||||
component: WalletManagement,
|
||||
} as ComponentMeta<typeof WalletManagement>;
|
||||
|
||||
const Template: ComponentStory<typeof WalletManagement> = () => {
|
||||
return <WalletManagement />;
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {};
|
@ -0,0 +1,62 @@
|
||||
// =============================================================================
|
||||
// Copyright 2022 Haveno
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
import { beforeAll, describe, expect, it, vi } from "vitest";
|
||||
import { render, waitForElementToBeRemoved } from "@testing-library/react";
|
||||
import { AppProviders } from "@atoms/AppProviders";
|
||||
import { WalletManagement } from ".";
|
||||
import { SeedPhrase } from "./SeedPhrase";
|
||||
|
||||
describe("molecules::WalletManagement", () => {
|
||||
beforeAll(() => {
|
||||
vi.mock("@hooks/haveno/useValidatePassword", () => ({
|
||||
useValidatePassword: () => ({
|
||||
isLoading: false,
|
||||
isSuccess: true,
|
||||
data: true,
|
||||
}),
|
||||
}));
|
||||
|
||||
vi.mock("@hooks/haveno/useXmrSeed", () => ({
|
||||
useXmrSeed: () => ({
|
||||
isLoading: true,
|
||||
isSuccess: true,
|
||||
data: "baptism ounce solved gimmick cafe absorb pouch gesture fawns degrees bikini inline island oncoming menu tissue cajun inwardly chlorine popular sleepless taboo aces arises popular",
|
||||
}),
|
||||
}));
|
||||
});
|
||||
|
||||
it("renders loading state", () => {
|
||||
const { asFragment } = render(
|
||||
<AppProviders>
|
||||
<WalletManagement />
|
||||
</AppProviders>
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders after loading data", async () => {
|
||||
const { asFragment, queryByText } = render(
|
||||
<AppProviders>
|
||||
<SeedPhrase />
|
||||
</AppProviders>
|
||||
);
|
||||
if (queryByText("Loading...")) {
|
||||
await waitForElementToBeRemoved(() => queryByText("Loading..."));
|
||||
}
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -0,0 +1,109 @@
|
||||
// =============================================================================
|
||||
// Copyright 2022 Haveno
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
import { useState } from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { useForm } from "@mantine/hooks";
|
||||
import { Group, Space, Stack } from "@mantine/core";
|
||||
import { showNotification } from "@mantine/notifications";
|
||||
import { Button } from "@atoms/Buttons";
|
||||
import { PasswordInput } from "@atoms/PasswordInput";
|
||||
import { useValidatePassword } from "@hooks/haveno/useValidatePassword";
|
||||
import { LangKeys } from "@constants/lang";
|
||||
import { SeedPhrase } from "./SeedPhrase";
|
||||
|
||||
export function WalletManagement() {
|
||||
const [isRevealed, setRevealed] = useState(false);
|
||||
const { getInputProps, onSubmit, values, reset } = useForm<FormValues>({
|
||||
initialValues: {
|
||||
password: "",
|
||||
},
|
||||
});
|
||||
|
||||
const { refetch: validatePassword } = useValidatePassword(
|
||||
{
|
||||
password: values.password,
|
||||
},
|
||||
{
|
||||
enabled: false,
|
||||
}
|
||||
);
|
||||
|
||||
const handleSubmit = () => {
|
||||
validatePassword().then(({ data: isValidPassword }) => {
|
||||
if (isValidPassword) {
|
||||
setRevealed(true);
|
||||
reset();
|
||||
} else {
|
||||
setRevealed(false);
|
||||
showNotification({
|
||||
color: "red",
|
||||
title: "Invalid password",
|
||||
message: "Please check your password",
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
{isRevealed ? (
|
||||
<Stack>
|
||||
<SeedPhrase />
|
||||
<Space h="lg" />
|
||||
<Group position="left">
|
||||
<Button
|
||||
type="submit"
|
||||
onClick={() => {
|
||||
setRevealed(false);
|
||||
}}
|
||||
>
|
||||
Hide Seed Phrase
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
) : (
|
||||
<form onSubmit={onSubmit(handleSubmit)}>
|
||||
<Stack>
|
||||
<Space h="sm" />
|
||||
<PasswordInput
|
||||
autoFocus
|
||||
id="password"
|
||||
required
|
||||
label={
|
||||
<FormattedMessage
|
||||
id={LangKeys.AccountWalletPassword}
|
||||
defaultMessage="Password"
|
||||
/>
|
||||
}
|
||||
{...getInputProps("password")}
|
||||
/>
|
||||
<Space h="lg" />
|
||||
<Group position="right">
|
||||
<Button type="submit" disabled={values.password ? false : true}>
|
||||
Reveal Seed Phrase
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</form>
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
interface FormValues {
|
||||
password: string;
|
||||
}
|
@ -0,0 +1,494 @@
|
||||
// Vitest Snapshot v1
|
||||
|
||||
exports[`molecules::WalletManagement > renders after loading data 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mantine-Stack-root mantine-lfk3cq"
|
||||
>
|
||||
<div
|
||||
class="mantine-63n06h"
|
||||
/>
|
||||
<div
|
||||
class="mantine-Text-root mantine-1ogvxnc"
|
||||
>
|
||||
Loading Wallet Seeds...
|
||||
</div>
|
||||
<ol
|
||||
class="mantine-List-root mantine-14df5ct"
|
||||
>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
baptism
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
ounce
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
solved
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
gimmick
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
cafe
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
absorb
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
pouch
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
gesture
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
fawns
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
degrees
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
bikini
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
inline
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
island
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
oncoming
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
menu
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
tissue
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
cajun
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
inwardly
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
chlorine
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
popular
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
sleepless
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
taboo
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
aces
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
arises
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Group-root mantine-1qkd5ve"
|
||||
>
|
||||
<li
|
||||
class="mantine-List-item mantine-Group-child mantine-xm6zd"
|
||||
>
|
||||
<div
|
||||
class="__mantine-ref-itemWrapper mantine-1hf9p21 mantine-List-itemWrapper"
|
||||
>
|
||||
<span>
|
||||
popular
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
</ol>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`molecules::WalletManagement > renders loading state 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mantine-Stack-root mantine-lfk3cq"
|
||||
>
|
||||
<form>
|
||||
<div
|
||||
class="mantine-Stack-root mantine-lfk3cq"
|
||||
>
|
||||
<div
|
||||
class="mantine-78ek8g"
|
||||
/>
|
||||
<div
|
||||
class="mantine-PasswordInput-root mantine-14qek68"
|
||||
>
|
||||
<label
|
||||
class="mantine-PasswordInput-label mantine-1bjo575"
|
||||
for="password"
|
||||
id="password-label"
|
||||
>
|
||||
Password
|
||||
<span
|
||||
class="mantine-1wc35tu mantine-PasswordInput-required"
|
||||
>
|
||||
*
|
||||
</span>
|
||||
</label>
|
||||
<div
|
||||
class="mantine-PasswordInput-wrapper mantine-12sbrde"
|
||||
>
|
||||
<div
|
||||
aria-invalid="false"
|
||||
class="mantine-PasswordInput-defaultVariant mantine-PasswordInput-input mantine-PasswordInput-input mantine-nakpsh"
|
||||
>
|
||||
<input
|
||||
class="mantine-PasswordInput-innerInput mantine-17c0t6q"
|
||||
id="password"
|
||||
required=""
|
||||
type="password"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-o3oqoy mantine-PasswordInput-rightSection"
|
||||
>
|
||||
<button
|
||||
aria-hidden="true"
|
||||
class="mantine-ActionIcon-hover mantine-ActionIcon-root mantine-PasswordInput-visibilityToggle mantine-910bvd"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
height="15"
|
||||
viewBox="0 0 15 15"
|
||||
width="15"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M7.5 11C4.80285 11 2.52952 9.62184 1.09622 7.50001C2.52952 5.37816 4.80285 4 7.5 4C10.1971 4 12.4705 5.37816 13.9038 7.50001C12.4705 9.62183 10.1971 11 7.5 11ZM7.5 3C4.30786 3 1.65639 4.70638 0.0760002 7.23501C-0.0253338 7.39715 -0.0253334 7.60288 0.0760014 7.76501C1.65639 10.2936 4.30786 12 7.5 12C10.6921 12 13.3436 10.2936 14.924 7.76501C15.0253 7.60288 15.0253 7.39715 14.924 7.23501C13.3436 4.70638 10.6921 3 7.5 3ZM7.5 9.5C8.60457 9.5 9.5 8.60457 9.5 7.5C9.5 6.39543 8.60457 5.5 7.5 5.5C6.39543 5.5 5.5 6.39543 5.5 7.5C5.5 8.60457 6.39543 9.5 7.5 9.5Z"
|
||||
fill="currentColor"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-63n06h"
|
||||
/>
|
||||
<div
|
||||
class="mantine-Group-root mantine-147cgkf"
|
||||
>
|
||||
<button
|
||||
class="mantine-Button-filled mantine-Button-root mantine-Group-child mantine-s2bdxi"
|
||||
disabled=""
|
||||
type="submit"
|
||||
>
|
||||
<div
|
||||
class="mantine-3xbgk5 mantine-Button-inner"
|
||||
>
|
||||
<span
|
||||
class="mantine-qo1k2 mantine-Button-label"
|
||||
>
|
||||
Reveal Seed Phrase
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
@ -0,0 +1,17 @@
|
||||
// =============================================================================
|
||||
// Copyright 2022 Haveno
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
export * from "./WalletManagement";
|
@ -50,4 +50,7 @@ export enum LangKeys {
|
||||
AccountSecurityFieldCurrentPassword = "account.security.field.currentPassword",
|
||||
AccountSecurityFieldPasswordFormatMsg = "account.security.field.password.format.message",
|
||||
AccountSecurityFieldRepeatPasswordMatchMsg = "account.security.field.repeatPassword.match.message",
|
||||
AccountWalletTitle = "account.wallet.title",
|
||||
AccountWalletDesc = "account.wallet.desc",
|
||||
AccountWalletPassword = "account.wallet.field.password",
|
||||
}
|
||||
|
@ -58,6 +58,10 @@ const LangPackEN: { [key in LangKeys]: string } = {
|
||||
[LangKeys.AccountSecurityFieldRepeatPasswordMatchMsg]:
|
||||
"Passwords don't match",
|
||||
[LangKeys.CreatePassword]: "Create password",
|
||||
[LangKeys.AccountWalletTitle]: "Your wallet details",
|
||||
[LangKeys.AccountWalletDesc]:
|
||||
"The Haveno wallet is permanently connected to your account. Solely saving your seed phrase is not enough to recover your account, you need to download a backup of your account, which you can download via the backup section.",
|
||||
[LangKeys.AccountWalletPassword]: "Password",
|
||||
};
|
||||
|
||||
export default LangPackEN;
|
||||
|
@ -59,6 +59,10 @@ const LangPackES: { [key in LangKeys]: string } = {
|
||||
[LangKeys.AccountSecurityFieldRepeatPasswordMatchMsg]:
|
||||
"La confirmación de la contraseña no coincide con la contraseña.",
|
||||
[LangKeys.CreatePassword]: "Crear contraseña",
|
||||
[LangKeys.AccountWalletTitle]: "Detalles de tu billetera",
|
||||
[LangKeys.AccountWalletDesc]:
|
||||
"La billetera Haveno está permanentemente conectada a su cuenta. Solo guardar su frase inicial no es suficiente para recuperar su cuenta, necesita descargar una copia de seguridad de su cuenta, que puede descargar a través de la sección de copia de seguridad.",
|
||||
[LangKeys.AccountWalletPassword]: "contraseña",
|
||||
};
|
||||
|
||||
export default LangPackES;
|
||||
|
@ -26,11 +26,13 @@ export enum QueryKeys {
|
||||
Prices = "Haveno.Prices",
|
||||
PrimaryAddress = "Haveno.PrimaryAddress",
|
||||
SyncStatus = "Haveno.SyncStatus",
|
||||
XmrSeed = "Haveno.XmrSeed",
|
||||
|
||||
// Storage
|
||||
StorageAccountInfo = "Storage.AccountInfo",
|
||||
StoragePreferences = "Storage.Preferences",
|
||||
StorageRemoteMoneroNode = "Storage.RemoteMoneroNode",
|
||||
StorageIsPasswordValid = "Storage.IsPasswordValid",
|
||||
|
||||
// Others
|
||||
AuthSession = "AuthSession",
|
||||
|
45
packages/renderer/src/hooks/haveno/useValidatePassword.ts
Normal file
45
packages/renderer/src/hooks/haveno/useValidatePassword.ts
Normal file
@ -0,0 +1,45 @@
|
||||
// =============================================================================
|
||||
// Copyright 2022 Haveno
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
import { QueryKeys } from "@constants/query-keys";
|
||||
import { useQuery } from "react-query";
|
||||
|
||||
interface Variables {
|
||||
password: string;
|
||||
}
|
||||
|
||||
interface Options {
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
export function useValidatePassword(variables: Variables, options?: Options) {
|
||||
return useQuery<boolean>(
|
||||
QueryKeys.StorageIsPasswordValid,
|
||||
async () => {
|
||||
try {
|
||||
const authToken = await window.electronStore.verifyPassword(
|
||||
variables.password
|
||||
);
|
||||
return Boolean(authToken);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
{
|
||||
enabled: options?.enabled ?? true,
|
||||
}
|
||||
);
|
||||
}
|
26
packages/renderer/src/hooks/haveno/useXmrSeed.ts
Normal file
26
packages/renderer/src/hooks/haveno/useXmrSeed.ts
Normal file
@ -0,0 +1,26 @@
|
||||
// =============================================================================
|
||||
// Copyright 2022 Haveno
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
import { useQuery } from "react-query";
|
||||
import { QueryKeys } from "@constants/query-keys";
|
||||
import { useHavenoClient } from "./useHavenoClient";
|
||||
|
||||
export function useXmrSeed() {
|
||||
const client = useHavenoClient();
|
||||
return useQuery(QueryKeys.XmrSeed, async () => {
|
||||
return client.getXmrSeed();
|
||||
});
|
||||
}
|
@ -14,12 +14,38 @@
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
import { Box, createStyles, Group, Stack } from "@mantine/core";
|
||||
import { BodyText, Heading } from "@atoms/Typography";
|
||||
import { WalletManagement } from "@organisms/WalletManagement/WalletManagement";
|
||||
import { AccountLayout } from "@templates/AccountLayout";
|
||||
import { LangKeys } from "@constants/lang";
|
||||
|
||||
export function Wallet() {
|
||||
const { classes } = useStyles();
|
||||
return (
|
||||
<AccountLayout>
|
||||
<h1>Account Wallet</h1>
|
||||
<Box>
|
||||
<Stack spacing="lg" className={classes.content}>
|
||||
<Group spacing="sm">
|
||||
<Heading stringId={LangKeys.AccountWalletTitle} order={3}>
|
||||
Your wallet details
|
||||
</Heading>
|
||||
<BodyText heavy stringId={LangKeys.AccountWalletDesc} size="md">
|
||||
The Haveno wallet is permanently connected to your account. Solely
|
||||
saving your seed phrase is not enough to recover your account, you
|
||||
need to download a backup of your account, which you can download
|
||||
via the backup section.
|
||||
</BodyText>
|
||||
</Group>
|
||||
</Stack>
|
||||
<WalletManagement />
|
||||
</Box>
|
||||
</AccountLayout>
|
||||
);
|
||||
}
|
||||
|
||||
const useStyles = createStyles((theme) => ({
|
||||
content: {
|
||||
maxWidth: theme.other.contentWidthMd,
|
||||
},
|
||||
}));
|
||||
|
Loading…
x
Reference in New Issue
Block a user