diff --git a/src/components/Modal/ModalImportKeys/ModalImportKeys.tsx b/src/components/Modal/ModalImportKeys/ModalImportKeys.tsx
index bf33ab7..c9913e4 100644
--- a/src/components/Modal/ModalImportKeys/ModalImportKeys.tsx
+++ b/src/components/Modal/ModalImportKeys/ModalImportKeys.tsx
@@ -17,6 +17,7 @@ import { useDebounce } from 'use-debounce'
import { fetchNip05 } from '@/utils/helpers/helpers'
import { DOMAIN } from '@/utils/consts'
import { CheckmarkIcon } from '@/assets'
+import { getPublicKey, nip19 } from 'nostr-tools'
const FORM_DEFAULT_VALUES = {
username: '',
@@ -42,35 +43,71 @@ export const ModalImportKeys = () => {
mode: 'onSubmit',
})
const [isLoading, setIsLoading] = useState(false)
- const [isAvailable, setIsAvailable] = useState(false)
+ const [nameNpub, setNameNpub] = useState('')
+ const [isTakenByNsec, setIsTakenByNsec] = useState(false)
+ const [isBadNsec, setIsBadNsec] = useState(false)
const enteredUsername = watch('username')
+ const enteredNsec = watch('nsec')
const [debouncedUsername] = useDebounce(enteredUsername, 100)
+ const [debouncedNsec] = useDebounce(enteredNsec, 100)
const checkIsUsernameAvailable = useCallback(async () => {
if (!debouncedUsername.trim().length) return undefined
const npubNip05 = await fetchNip05(`${debouncedUsername}@${DOMAIN}`)
-
- setIsAvailable(!npubNip05)
+ setNameNpub(npubNip05 || '')
}, [debouncedUsername])
useEffect(() => {
checkIsUsernameAvailable()
}, [checkIsUsernameAvailable])
+ const checkNsecUsername = useCallback(async () => {
+ if (!debouncedNsec.trim().length) {
+ setIsTakenByNsec(false)
+ setIsBadNsec(false)
+ return
+ }
+ try {
+ const { type, data } = nip19.decode(debouncedNsec)
+ const ok = type === 'nsec';
+ setIsBadNsec(!ok)
+ if (ok) {
+ const npub = nip19.npubEncode(
+ // @ts-ignore
+ getPublicKey(data))
+ setIsTakenByNsec(!!nameNpub && nameNpub === npub)
+ } else {
+ setIsTakenByNsec(false)
+ }
+ } catch {
+ setIsBadNsec(true)
+ setIsTakenByNsec(false)
+ return
+ }
+}, [debouncedNsec])
+
+ useEffect(() => {
+ checkNsecUsername()
+ }, [checkNsecUsername])
+
const cleanUpStates = useCallback(() => {
hidePassword()
reset()
setIsLoading(false)
- setIsAvailable(false)
+ setNameNpub('')
+ setIsTakenByNsec(false)
+ setIsBadNsec(false)
}, [reset, hidePassword])
const notify = useEnqueueSnackbar()
const navigate = useNavigate()
const submitHandler = async (values: FormInputType) => {
- if (isLoading || !isAvailable) return undefined
+ if (isLoading) return undefined
try {
const { nsec, username } = values
+ if (!nsec || !username) throw new Error("Enter username and nsec")
+ if (nameNpub && !isTakenByNsec) throw new Error("Name taken")
setIsLoading(true)
const k: any = await swicCall('importKey', username, nsec)
notify('Key imported!', 'success')
@@ -88,9 +125,11 @@ export const ModalImportKeys = () => {
}
}, [isModalOpened, cleanUpStates])
- const getInputHelperText = () => {
+ const getNameHelperText = () => {
if (!enteredUsername) return "Don't worry, username can be changed later."
- if (!isAvailable) return 'Already taken'
+ if (isTakenByNsec) return 'Name matches your key'
+ if (isBadNsec) return 'Invalid nsec'
+ if (nameNpub) return 'Already taken'
return (
<>
Available
@@ -98,7 +137,13 @@ export const ModalImportKeys = () => {
)
}
- const inputHelperText = getInputHelperText()
+ const getNsecHelperText = () => {
+ if (isBadNsec) return 'Invalid nsec'
+ return 'Keys stay on your device.'
+ }
+
+ const nameHelperText = getNameHelperText()
+ const nsecHelperText = getNsecHelperText()
return (
@@ -116,14 +161,14 @@ export const ModalImportKeys = () => {
endAdornment={@{DOMAIN}}
{...register('username')}
error={!!errors.username}
- helperText={inputHelperText}
+ helperText={nameHelperText}
helperTextProps={{
sx: {
'&.helper_text': {
color:
- enteredUsername && isAvailable
+ enteredUsername && (isTakenByNsec || !nameNpub)
? theme.palette.success.main
- : enteredUsername && !isAvailable
+ : enteredUsername && nameNpub
? theme.palette.error.main
: theme.palette.textSecondaryDecorate.main,
},
@@ -137,11 +182,13 @@ export const ModalImportKeys = () => {
{...register('nsec')}
error={!!errors.nsec}
{...inputProps}
- helperText="Keys stay on your device."
+ helperText={nsecHelperText}
helperTextProps={{
sx: {
'&.helper_text': {
- color: theme.palette.textSecondaryDecorate.main,
+ color: isBadNsec
+ ? theme.palette.error.main
+ : theme.palette.textSecondaryDecorate.main,
},
},
}}