mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-03-17 21:31:43 +01:00
Add "Migrate to signing device" option in account manager
This commit is contained in:
parent
2faa014720
commit
697d4c67a2
5
.changeset/angry-flowers-turn.md
Normal file
5
.changeset/angry-flowers-turn.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"nostrudel": minor
|
||||
---
|
||||
|
||||
Add "Migrate to signing device" option in account manager
|
@ -49,7 +49,7 @@
|
||||
"applesauce-lists": "^0.10.0",
|
||||
"applesauce-net": "^0.10.0",
|
||||
"applesauce-react": "^0.10.0",
|
||||
"applesauce-signer": "^0.10.0",
|
||||
"applesauce-signer": "0.0.0-next-20241218172722",
|
||||
"bech32": "^2.0.0",
|
||||
"blossom-client-sdk": "^2.1.0",
|
||||
"blossom-drive-sdk": "^0.4.1",
|
||||
|
10
pnpm-lock.yaml
generated
10
pnpm-lock.yaml
generated
@ -112,8 +112,8 @@ importers:
|
||||
specifier: ^0.10.0
|
||||
version: 0.10.0(typescript@5.7.2)
|
||||
applesauce-signer:
|
||||
specifier: ^0.10.0
|
||||
version: 0.10.0(typescript@5.7.2)
|
||||
specifier: 0.0.0-next-20241218172722
|
||||
version: 0.0.0-next-20241218172722(typescript@5.7.2)
|
||||
bech32:
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0
|
||||
@ -1927,8 +1927,8 @@ packages:
|
||||
applesauce-react@0.10.0:
|
||||
resolution: {integrity: sha512-du4EC4cBM9bWbyRVllciPCNwwwKTEsTqSjsB5/h/tktfG/2ubiZfUsDD9o55o0eWx/drDabIN4sjnv3OEwvXww==}
|
||||
|
||||
applesauce-signer@0.10.0:
|
||||
resolution: {integrity: sha512-2Cn2ZUxk47cBJBFoUl9DB37mjgg8/8GwTAG7csPqtooJ4nUh0ylO4Gh1Mr/401Lc8tjZJvpVBySWpCeXrnG1rQ==}
|
||||
applesauce-signer@0.0.0-next-20241218172722:
|
||||
resolution: {integrity: sha512-0DvkuVLCiFr7CjLeUr+AHxtiLBwOf7TiDBmpbVTdDgmNYo/hlvYOvgVDfISkpB8DRE1/44BlWBXFxbKmfVWkxg==}
|
||||
|
||||
argparse@1.0.10:
|
||||
resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
|
||||
@ -6469,7 +6469,7 @@ snapshots:
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
applesauce-signer@0.10.0(typescript@5.7.2):
|
||||
applesauce-signer@0.0.0-next-20241218172722(typescript@5.7.2):
|
||||
dependencies:
|
||||
'@noble/hashes': 1.6.1
|
||||
'@noble/secp256k1': 1.7.1
|
||||
|
62
src/views/settings/accounts/components/migrate-to-device.tsx
Normal file
62
src/views/settings/accounts/components/migrate-to-device.tsx
Normal file
@ -0,0 +1,62 @@
|
||||
import { Button, Flex, Heading, Link, useToast } from "@chakra-ui/react";
|
||||
import { PasswordSigner, SerialPortSigner, SimpleSigner } from "applesauce-signer";
|
||||
import { useState } from "react";
|
||||
|
||||
import useAsyncErrorHandler from "../../../../hooks/use-async-error-handler";
|
||||
import useCurrentAccount from "../../../../hooks/use-current-account";
|
||||
import SerialPortAccount from "../../../../classes/accounts/serial-port-account";
|
||||
import accountService from "../../../../services/account";
|
||||
|
||||
export default function MigrateAccountToDevice() {
|
||||
if (!SerialPortSigner.SUPPORTED) return null;
|
||||
|
||||
const toast = useToast();
|
||||
const current = useCurrentAccount();
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const migrate = useAsyncErrorHandler(async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
if (!current?.signer) throw new Error("Account missing signer");
|
||||
const device = new SerialPortSigner();
|
||||
|
||||
if (current.signer instanceof SimpleSigner) {
|
||||
// send key to device
|
||||
await device.restore(current.signer.key);
|
||||
} else if (current.signer instanceof PasswordSigner) {
|
||||
// unlock the signer first
|
||||
if (!current.signer.unlocked) {
|
||||
const password = window.prompt("Decryption password");
|
||||
if (password === null) throw new Error("Password required");
|
||||
await current.signer.unlock(password);
|
||||
}
|
||||
|
||||
await device.restore(current.signer.key!);
|
||||
} else throw new Error("Unsupported signer type");
|
||||
|
||||
// replace existing account
|
||||
const deviceAccount = new SerialPortAccount(current.pubkey);
|
||||
accountService.replaceAccount(current.pubkey, deviceAccount);
|
||||
accountService.switchAccount(deviceAccount.pubkey);
|
||||
} catch (error) {
|
||||
if (error instanceof Error) toast({ description: error.message, status: "error" });
|
||||
}
|
||||
setLoading(false);
|
||||
}, [setLoading, current]);
|
||||
|
||||
return (
|
||||
<Flex direction="column" gap="2">
|
||||
<Heading size="md" mt="2">
|
||||
Migrate to{" "}
|
||||
<Link isExternal href="https://github.com/lnbits/nostr-signing-device" color="blue.500">
|
||||
nostr-signing-device
|
||||
</Link>
|
||||
</Heading>
|
||||
<Flex gap="2" maxW="lg">
|
||||
<Button colorScheme="purple" isLoading={loading} onClick={migrate}>
|
||||
Start migration
|
||||
</Button>
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
}
|
@ -13,10 +13,10 @@ import {
|
||||
import { useForm } from "react-hook-form";
|
||||
import { PasswordSigner } from "applesauce-signer";
|
||||
|
||||
import useCurrentAccount from "../../../hooks/use-current-account";
|
||||
import EyeOff from "../../../components/icons/eye-off";
|
||||
import Eye from "../../../components/icons/eye";
|
||||
import { CopyIconButton } from "../../../components/copy-icon-button";
|
||||
import useCurrentAccount from "../../../../hooks/use-current-account";
|
||||
import EyeOff from "../../../../components/icons/eye-off";
|
||||
import Eye from "../../../../components/icons/eye";
|
||||
import { CopyIconButton } from "../../../../components/copy-icon-button";
|
||||
|
||||
const fake = Array(48).fill("x");
|
||||
|
@ -15,12 +15,12 @@ import { encrypt } from "nostr-tools/nip49";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { SimpleSigner } from "applesauce-signer";
|
||||
|
||||
import useCurrentAccount from "../../../hooks/use-current-account";
|
||||
import EyeOff from "../../../components/icons/eye-off";
|
||||
import Eye from "../../../components/icons/eye";
|
||||
import { CopyIconButton } from "../../../components/copy-icon-button";
|
||||
import accountService from "../../../services/account";
|
||||
import PasswordAccount from "../../../classes/accounts/password-account";
|
||||
import useCurrentAccount from "../../../../hooks/use-current-account";
|
||||
import EyeOff from "../../../../components/icons/eye-off";
|
||||
import Eye from "../../../../components/icons/eye";
|
||||
import { CopyIconButton } from "../../../../components/copy-icon-button";
|
||||
import accountService from "../../../../services/account";
|
||||
import PasswordAccount from "../../../../classes/accounts/password-account";
|
||||
|
||||
const fake = Array(48).fill("x");
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Box, Button, ButtonGroup, Divider, Flex, Heading, Text } from "@chakra-ui/react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { PasswordSigner, SimpleSigner } from "applesauce-signer";
|
||||
import { PasswordSigner, SerialPortSigner, SimpleSigner } from "applesauce-signer";
|
||||
import { useObservable } from "applesauce-react/hooks";
|
||||
|
||||
import VerticalPageLayout from "../../../components/vertical-page-layout";
|
||||
@ -10,21 +10,22 @@ import UserName from "../../../components/user/user-name";
|
||||
import UserDnsIdentity from "../../../components/user/user-dns-identity";
|
||||
import accountService from "../../../services/account";
|
||||
import AccountTypeBadge from "../../../components/account-info-badge";
|
||||
import SimpleSignerBackup from "./simple-signer-backup";
|
||||
import PasswordSignerBackup from "./password-signer-backup";
|
||||
import SimpleSignerBackup from "./components/simple-signer-backup";
|
||||
import PasswordSignerBackup from "./components/password-signer-backup";
|
||||
import { ReactNode } from "react";
|
||||
import MigrateAccountToDevice from "./components/migrate-to-device";
|
||||
|
||||
function AccountBackup() {
|
||||
const account = useCurrentAccount()!;
|
||||
|
||||
if (account.signer instanceof PasswordSigner && account.signer.ncryptsec) {
|
||||
return <PasswordSignerBackup />;
|
||||
}
|
||||
|
||||
if (account.signer instanceof SimpleSigner && account.signer.key) {
|
||||
return <SimpleSignerBackup />;
|
||||
}
|
||||
|
||||
return null;
|
||||
return (
|
||||
<>
|
||||
{account.signer instanceof SimpleSigner && account.signer.key && <SimpleSignerBackup />}
|
||||
{account.signer instanceof PasswordSigner && account.signer.ncryptsec && <SimpleSignerBackup />}
|
||||
{(account.signer instanceof SimpleSigner || account.signer instanceof PasswordSigner) &&
|
||||
SerialPortSigner.SUPPORTED && <MigrateAccountToDevice />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default function AccountSettings() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user