feat: add NIP-43 relay access metadata support

Add feed and detail rendering for kind 13534 (Relay Members) events,
and enable all NIP-43 kind constants for relay access management.

- Add RelayMembersRenderer with feed and detail views
- Enable kind constants: 13534, 28934, 28935, 28936
- Use Shield icon to represent relay access control
- Extract members from NIP-43's "member" tags (not standard "p" tags)
This commit is contained in:
Claude
2026-01-15 11:11:50 +00:00
parent 1ce784561a
commit 5b83212915
3 changed files with 115 additions and 28 deletions

View File

@@ -0,0 +1,81 @@
import { Shield, Users } from "lucide-react";
import { getTagValues } from "@/lib/nostr-utils";
import {
BaseEventProps,
BaseEventContainer,
ClickableEventTitle,
} from "./BaseEventRenderer";
import { PubkeyListFull } from "../lists";
import type { NostrEvent } from "@/types/nostr";
/**
* Kind 13534 Renderer - Relay Members (Feed View)
* NIP-43 relay membership list
*
* Uses "member" tags instead of standard "p" tags:
* ["member", "<hex-pubkey>"]
*/
export function RelayMembersRenderer({ event }: BaseEventProps) {
const members = getTagValues(event, "member");
if (members.length === 0) {
return (
<BaseEventContainer event={event}>
<div className="text-xs text-muted-foreground italic">
Empty membership list
</div>
</BaseEventContainer>
);
}
return (
<BaseEventContainer event={event}>
<div className="flex flex-col gap-2">
<ClickableEventTitle
event={event}
className="flex items-center gap-1.5 text-sm font-medium"
>
<Shield className="size-4 text-muted-foreground" />
<span>Relay Members</span>
</ClickableEventTitle>
<div className="flex flex-col gap-1.5 text-xs">
<div className="flex items-center gap-1.5">
<Users className="size-3.5 text-muted-foreground" />
<span>
{members.length} {members.length === 1 ? "member" : "members"}
</span>
</div>
</div>
</div>
</BaseEventContainer>
);
}
/**
* Kind 13534 Detail View - Full relay membership list
*/
export function RelayMembersDetailRenderer({ event }: { event: NostrEvent }) {
const members = getTagValues(event, "member");
return (
<div className="flex flex-col gap-6 p-4">
<div className="flex items-center gap-2">
<Shield className="size-6 text-muted-foreground" />
<span className="text-lg font-semibold">Relay Members</span>
</div>
{members.length > 0 ? (
<PubkeyListFull
pubkeys={members}
label="Members"
icon={<Users className="size-5" />}
/>
) : (
<div className="text-sm text-muted-foreground italic">
Empty membership list
</div>
)}
</div>
);
}

View File

@@ -67,6 +67,10 @@ import { ZapstoreAppSetDetailRenderer } from "./ZapstoreAppSetDetailRenderer";
import { ZapstoreReleaseRenderer } from "./ZapstoreReleaseRenderer";
import { ZapstoreReleaseDetailRenderer } from "./ZapstoreReleaseDetailRenderer";
import { GroupMetadataRenderer } from "./GroupMetadataRenderer";
import {
RelayMembersRenderer,
RelayMembersDetailRenderer,
} from "./RelayMembersRenderer";
// NIP-51 List Renderers
import { MuteListRenderer, MuteListDetailRenderer } from "./MuteListRenderer";
import { PinListRenderer, PinListDetailRenderer } from "./PinListRenderer";
@@ -178,6 +182,7 @@ const kindRenderers: Record<number, React.ComponentType<BaseEventProps>> = {
10101: WikiAuthorsRenderer, // Good Wiki Authors (NIP-51)
10102: WikiRelaysRenderer, // Good Wiki Relays (NIP-51)
10317: Kind10317Renderer, // User Grasp List (NIP-34)
13534: RelayMembersRenderer, // Relay Members (NIP-43)
30000: FollowSetRenderer, // Follow Sets (NIP-51)
30002: GenericRelayListRenderer, // Relay Sets (NIP-51)
30003: BookmarkSetRenderer, // Bookmark Sets (NIP-51)
@@ -268,6 +273,7 @@ const detailRenderers: Record<
10101: WikiAuthorsDetailRenderer, // Good Wiki Authors Detail (NIP-51)
10102: WikiRelaysDetailRenderer, // Good Wiki Relays Detail (NIP-51)
10317: Kind10317DetailRenderer, // User Grasp List Detail (NIP-34)
13534: RelayMembersDetailRenderer, // Relay Members Detail (NIP-43)
30000: FollowSetDetailRenderer, // Follow Sets Detail (NIP-51)
30003: BookmarkSetDetailRenderer, // Bookmark Sets Detail (NIP-51)
30004: ArticleCurationSetDetailRenderer, // Article Curation Sets Detail (NIP-51)

View File

@@ -887,13 +887,13 @@ export const EVENT_KINDS: Record<number | string, EventKind> = {
nip: "47",
icon: Wallet,
},
// 13534: {
// kind: 13534,
// name: "Membership Lists",
// description: "Membership Lists",
// nip: "43",
// icon: Users,
// },
13534: {
kind: 13534,
name: "Relay Members",
description: "Relay membership list",
nip: "43",
icon: Shield,
},
// 17375: {
// kind: 17375,
// name: "Cashu Wallet Event",
@@ -950,27 +950,27 @@ export const EVENT_KINDS: Record<number | string, EventKind> = {
nip: "98",
icon: Key,
},
// 28934: {
// kind: 28934,
// name: "Join Request",
// description: "Join Request",
// nip: "43",
// icon: UserPlus,
// },
// 28935: {
// kind: 28935,
// name: "Invite Request",
// description: "Invite Request",
// nip: "43",
// icon: Mail,
// },
// 28936: {
// kind: 28936,
// name: "Leave Request",
// description: "Leave Request",
// nip: "43",
// icon: UserMinus,
// },
28934: {
kind: 28934,
name: "Join Request",
description: "Relay join request with invite code",
nip: "43",
icon: UserPlus,
},
28935: {
kind: 28935,
name: "Invite Request",
description: "Request invite code from relay",
nip: "43",
icon: Mail,
},
28936: {
kind: 28936,
name: "Leave Request",
description: "Request to revoke relay access",
nip: "43",
icon: UserMinus,
},
// Group Control
9000: {