diff --git a/src/services/dns-identity.ts b/src/services/dns-identity.ts index 2096cc355..66408e1b3 100644 --- a/src/services/dns-identity.ts +++ b/src/services/dns-identity.ts @@ -34,28 +34,31 @@ async function fetchAllIdentities(domain: string) { async function fetchIdentity(address: string) { const { name, domain } = parseAddress(address); if (!name || !domain) throw new Error("invalid address"); - const json = await fetch(`https://${domain}/.well-known/nostr.json?name=${name}`) - .then((res) => res.json() as Promise) - .then((json) => { - // convert all keys in names, and relays to lower case - if (json.names) { - for (const [name, pubkey] of Object.entries(json.names)) { - delete json.names[name]; - json.names[name.toLowerCase()] = pubkey; - } - } - if (json.relays) { - for (const [name, pubkey] of Object.entries(json.relays)) { - delete json.relays[name]; - json.relays[name.toLowerCase()] = pubkey; - } - } - return json; - }); - await addToCache(domain, json); + try { + const json = await fetch(`https://${domain}/.well-known/nostr.json?name=${name}`) + .then((res) => res.json() as Promise) + .then((json) => { + // convert all keys in names, and relays to lower case + if (json.names) { + for (const [name, pubkey] of Object.entries(json.names)) { + delete json.names[name]; + json.names[name.toLowerCase()] = pubkey; + } + } + if (json.relays) { + for (const [name, pubkey] of Object.entries(json.relays)) { + delete json.relays[name]; + json.relays[name.toLowerCase()] = pubkey; + } + } + return json; + }); - return getIdentityFromJson(name, domain, json); + await addToCache(domain, json); + + return getIdentityFromJson(name, domain, json); + } catch (e) {} } async function addToCache(domain: string, json: IdentityJson) { @@ -75,7 +78,6 @@ async function getIdentity(address: string, alwaysFetch = false) { const cached = await db.get("dnsIdentifiers", address); if (cached && !alwaysFetch) return cached; - // TODO: if it fails, maybe cache a failure message return fetchIdentity(address); } @@ -94,7 +96,10 @@ async function pruneCache() { const pending: Record | undefined> = {}; function dedupedGetIdentity(address: string, alwaysFetch = false) { if (pending[address]) return pending[address]; - return (pending[address] = getIdentity(address, alwaysFetch)); + return (pending[address] = getIdentity(address, alwaysFetch).then((v) => { + delete pending[address]; + return v; + })); } export const dnsIdentityService = { diff --git a/src/services/relay-info.ts b/src/services/relay-info.ts index 6bcb6580c..d2c62c868 100644 --- a/src/services/relay-info.ts +++ b/src/services/relay-info.ts @@ -41,7 +41,10 @@ const pending: Record | undefined> = {}; function dedupedGetIdentity(relay: string) { const request = pending[relay]; if (request) return request; - return (pending[relay] = getInfo(relay)); + return (pending[relay] = getInfo(relay).then((v) => { + delete pending[relay]; + return v; + })); } export const relayInfoService = { diff --git a/src/views/profile/edit.tsx b/src/views/profile/edit.tsx index e19975eeb..beb55882b 100644 --- a/src/views/profile/edit.tsx +++ b/src/views/profile/edit.tsx @@ -1,4 +1,14 @@ -import { Avatar, Button, Flex, FormControl, FormLabel, Input, Textarea, useToast } from "@chakra-ui/react"; +import { + Avatar, + Button, + Flex, + FormControl, + FormErrorMessage, + FormLabel, + Input, + Textarea, + useToast, +} from "@chakra-ui/react"; import moment from "moment"; import { useEffect, useMemo } from "react"; import { useForm } from "react-hook-form"; @@ -9,6 +19,7 @@ import { useReadRelayUrls, useWriteRelayUrls } from "../../hooks/use-client-rela import { useCurrentAccount } from "../../hooks/use-current-account"; import { useIsMobile } from "../../hooks/use-is-mobile"; import { useUserMetadata } from "../../hooks/use-user-metadata"; +import dnsIdentityService from "../../services/dns-identity"; import signingService from "../../services/signing"; import userMetadataService from "../../services/user-metadata"; import { DraftNostrEvent } from "../../types/nostr-event"; @@ -26,6 +37,7 @@ type FormData = { picture?: string; about?: string; website?: string; + nip05?: string; lightningAddress?: string; }; @@ -35,12 +47,13 @@ type MetadataFormProps = { }; const MetadataForm = ({ defaultValues, onSubmit }: MetadataFormProps) => { + const account = useCurrentAccount(); const isMobile = useIsMobile(); const { register, reset, handleSubmit, - getValues, + watch, formState: { errors, isSubmitting }, } = useForm({ mode: "onBlur", @@ -56,61 +69,89 @@ const MetadataForm = ({ defaultValues, onSubmit }: MetadataFormProps) => {
- + Display Name - + + {errors.displayName?.message} - + Username - {errors.username?.message} + {errors.username?.message} - + Picture - + - + - + + NIP-05 ID + { + if (!address) return true; + if (!address.includes("@")) return "invalid address"; + const id = await dnsIdentityService.getIdentity(address); + if (!id) return "cant find NIP-05 ID"; + if (id.pubkey !== account.pubkey) return "Pubkey dose not match"; + return true; + }, + })} + /> + {errors.nip05?.message} + + Website - + About