feat: cache nip05 verifications
This commit is contained in:
@ -1,36 +1,41 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useQuery } from "react-query";
|
||||
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faCheck, faSpinner, faTriangleExclamation } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
import './Nip05.css'
|
||||
|
||||
export function useIsVerified(nip05, pubkey) {
|
||||
const [isVerified, setIsVerified] = useState(false)
|
||||
const [couldNotVerify, setCouldNotVerify] = useState(false)
|
||||
const [name, domain] = nip05 ? nip05.split('@') : []
|
||||
|
||||
useEffect(() => {
|
||||
if (!nip05 || !pubkey) {
|
||||
return
|
||||
}
|
||||
setCouldNotVerify(false)
|
||||
setIsVerified(false)
|
||||
|
||||
fetch(`https://${domain}/.well-known/nostr.json?name=${encodeURIComponent(name)}`)
|
||||
function fetchNip05Pubkey(name, domain) {
|
||||
if (!name || !domain) {
|
||||
return Promise.resolve(null)
|
||||
}
|
||||
return fetch(`https://${domain}/.well-known/nostr.json?name=${encodeURIComponent(name)}`)
|
||||
.then((res) => res.json())
|
||||
.then(({ names }) => {
|
||||
if (names && names[name]) {
|
||||
setIsVerified(names[name] === pubkey)
|
||||
return names[name]
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
setCouldNotVerify(true)
|
||||
console.error("Couldn't verifiy nip05")
|
||||
})
|
||||
}, [nip05, pubkey])
|
||||
}
|
||||
|
||||
return { name, domain: domain?.toLowerCase(), isVerified, couldNotVerify }
|
||||
const VERIFICATION_CACHE_TIME = 24 * 60 * 60 * 1000
|
||||
const VERIFICATION_STALE_TIMEOUT = 10 * 60 * 1000
|
||||
|
||||
export function useIsVerified(nip05, pubkey) {
|
||||
const [name, domain] = nip05 ? nip05.split('@') : []
|
||||
const address = domain && `${name}@${domain.toLowerCase()}`
|
||||
const { isLoading, isError, isSuccess, isIdle, data } = useQuery(
|
||||
['nip05', nip05],
|
||||
() => fetchNip05Pubkey(name, domain),
|
||||
{
|
||||
retry: false,
|
||||
cacheTime: VERIFICATION_CACHE_TIME,
|
||||
staleTime: VERIFICATION_STALE_TIMEOUT
|
||||
},
|
||||
)
|
||||
const isVerified = isSuccess && data === pubkey
|
||||
const cantVerify = isSuccess && data !== pubkey
|
||||
return { name, domain: domain?.toLowerCase(), isVerified, couldNotVerify: isError || cantVerify }
|
||||
}
|
||||
|
||||
const Nip05 = ({ name, domain, isVerified, couldNotVerify }) => {
|
||||
|
@ -43,9 +43,10 @@ function normalizeUser({ pubkey, about, nip05, name, display_name }: User) {
|
||||
return { pubkey, about, nip05, name, display_name }
|
||||
}
|
||||
|
||||
const Textarea = ({ onChange, ...rest }: any) => {
|
||||
// @ts-expect-error
|
||||
const { users } = useSelector(s => s.users)
|
||||
const Textarea = ({ users, onChange, ...rest }: any) => {
|
||||
const normalizedUsers = Object.keys(users).reduce((acc, pk) => {
|
||||
return {...acc, [pk]: normalizeUser(users[pk]) }
|
||||
}, {})
|
||||
const dbUsers = useLiveQuery(
|
||||
() => db.users.toArray().then(usrs => {
|
||||
return usrs.reduce((acc, usr) => {
|
||||
@ -53,8 +54,7 @@ const Textarea = ({ onChange, ...rest }: any) => {
|
||||
}, {})
|
||||
})
|
||||
)
|
||||
const cachedUsers = dbUsers ? dbUsers : {}
|
||||
const allUsers: User[] = Object.values({...cachedUsers, ...users})
|
||||
const allUsers: User[] = Object.values({...normalizedUsers, ...dbUsers})
|
||||
|
||||
return (
|
||||
<ReactTextareaAutocomplete
|
||||
|
10
src/index.js
10
src/index.js
@ -1,6 +1,7 @@
|
||||
import './index.css';
|
||||
|
||||
import React from 'react';
|
||||
import { QueryClient, QueryClientProvider } from 'react-query';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import { Provider } from 'react-redux'
|
||||
import {
|
||||
@ -28,6 +29,11 @@ import ChatPage from './pages/ChatPage';
|
||||
*/
|
||||
export const System = new NostrSystem();
|
||||
|
||||
/**
|
||||
* HTTP query provider
|
||||
*/
|
||||
const HTTP = new QueryClient()
|
||||
|
||||
const router = createBrowserRouter([
|
||||
{
|
||||
element: <Layout />,
|
||||
@ -81,7 +87,9 @@ const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<Provider store={Store}>
|
||||
<RouterProvider router={router} />
|
||||
<QueryClientProvider client={HTTP}>
|
||||
<RouterProvider router={router} />
|
||||
</QueryClientProvider>
|
||||
</Provider>
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
@ -59,7 +59,7 @@ export default function ProfilePage() {
|
||||
const lnurl = extractLnAddress(user?.lud16 || user?.lud06 || "");
|
||||
return (
|
||||
<div className="details">
|
||||
<p>{about}</p>
|
||||
<div>{about}</div>
|
||||
|
||||
{user?.website && (
|
||||
<div className="website f-ellipsis">
|
||||
|
Reference in New Issue
Block a user