snort/src/element/Nip05.tsx

86 lines
2.4 KiB
TypeScript
Raw Normal View History

2023-01-16 17:48:25 +00:00
import { useQuery } from "react-query";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
2023-01-16 23:20:15 +00:00
import { faSpinner, faTriangleExclamation } from "@fortawesome/free-solid-svg-icons";
2023-01-16 17:48:25 +00:00
import './Nip05.css'
import { HexKey } from "../nostr";
interface NostrJson {
names: Record<string, string>
}
async function fetchNip05Pubkey(name: string, domain: string) {
if (!name || !domain) {
return undefined;
}
const res = await fetch(`https://${domain}/.well-known/nostr.json?name=${encodeURIComponent(name)}`);
const data: NostrJson = await res.json();
const match = Object.keys(data.names).find(n => {
return n.toLowerCase() === name.toLowerCase();
});
return match ? data.names[match] : undefined;
}
const VERIFICATION_CACHE_TIME = 24 * 60 * 60 * 1000
const VERIFICATION_STALE_TIMEOUT = 10 * 60 * 1000
export function useIsVerified(pubkey: HexKey, nip05?: string) {
const [name, domain] = nip05 ? nip05.split('@') : []
const { isError, isSuccess, data } = useQuery(
['nip05', nip05],
() => fetchNip05Pubkey(name, domain),
{
retry: false,
retryOnMount: false,
cacheTime: VERIFICATION_CACHE_TIME,
staleTime: VERIFICATION_STALE_TIMEOUT,
},
)
const isVerified = isSuccess && data === pubkey
const cantVerify = isSuccess && data !== pubkey
return { isVerified, couldNotVerify: isError || cantVerify }
}
export interface Nip05Params {
nip05?: string,
pubkey: HexKey
}
const Nip05 = (props: Nip05Params) => {
const [name, domain] = props.nip05 ? props.nip05.split('@') : []
const isDefaultUser = name === '_'
const { isVerified, couldNotVerify } = useIsVerified(props.pubkey, props.nip05)
return (
2023-01-16 22:22:21 +00:00
<div className={`flex nip05${couldNotVerify ? " failed" : ""}`} onClick={(ev) => ev.stopPropagation()}>
2023-01-16 22:23:24 +00:00
{!isDefaultUser && (
<div className="nick">
{name}
</div>
)}
2023-01-16 17:48:25 +00:00
<div className={`domain text-gradient`} data-domain={domain?.toLowerCase()}>
{domain}
</div>
<span className="badge">
{!isVerified && !couldNotVerify && (
<FontAwesomeIcon
color={"var(--fg-color)"}
icon={faSpinner}
size="xs"
/>
)}
{couldNotVerify && (
<FontAwesomeIcon
color={"var(--error)"}
icon={faTriangleExclamation}
size="xs"
/>
)}
</span>
</div>
)
}
export default Nip05