SkateSpots/src/hooks/useCrewNip05.ts
shakespeare.diy dbae3a1501 Add soft NIP-05 verification for skaters (open directory + "Verified" filter)
Keeps the skater directory fully open — NIP-05 is a trust signal, not a gate:
- Extract reusable NIP-05 verification into lib/nip05.ts (parse, fetch well-known, verify against expected pubkey); refactor useCrewNip05 to use it
- New useSkaterVerifications hook: batch-fetches kind-0 metadata for all skaters and verifies each nip05 resolves to its own pubkey, returning a Set of verified pubkeys
- SkatersPage: add a "Verified (N)" toggle (disabled when none verified) that filters to genuinely verified skaters; show ✓ badge only for truly-verified skaters; verified-aware empty state
- NIP19Page profile: nip05 line now reflects real verification (lime ShieldCheck + "Verified" pill when the handle resolves to the key, muted grey otherwise)

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-09-02 21:51:11 +07:00

26 lines
999 B
TypeScript

import { useQuery } from '@tanstack/react-query';
import { verifyNip05, type Nip05Result } from '@/lib/nip05';
export type { Nip05Status } from '@/lib/nip05';
/**
* Verify a crew's optional NIP-05 identifier against its founder pubkey.
*
* The crew profile is authored by the founder, so a NIP-05 is legitimate only if
* the domain's `.well-known/nostr.json` maps the name to that same founder key.
* This works with ANY domain the crew controls (fully decentralized) — SkateSpots
* does not gatekeep the handle.
*/
export function useCrewNip05(nip05: string | undefined, founderPubkey: string | undefined) {
return useQuery<Nip05Result>({
queryKey: ['crew-nip05', nip05, founderPubkey],
queryFn: (c) => {
const signal = AbortSignal.any([c.signal, AbortSignal.timeout(6000)]);
return verifyNip05(nip05, founderPubkey, signal);
},
enabled: !!nip05 && !!founderPubkey,
staleTime: 10 * 60 * 1000, // 10 min
gcTime: 30 * 60 * 1000,
retry: 1,
});
}