diff --git a/.claude/commands/sync-nips.md b/.claude/commands/sync-nips.md
index 4aa39d0..139b9ee 100644
--- a/.claude/commands/sync-nips.md
+++ b/.claude/commands/sync-nips.md
@@ -21,7 +21,7 @@ Read the current file, then:
### VALID_NIPS array
- Add new NIP identifiers found upstream
- Remove NIPs no longer listed upstream (unless referenced by a kind in `kinds.ts`)
-- Maintain sort order: numeric first (`"01"`–`"99"`), then hexadecimal (`"7D"`, `"A0"`, etc.)
+- Maintain sort order: numeric first (`"01"`–`"99"`), then hexadecimal (`"5A"`, `"7D"`, `"A0"`, etc.)
- Preserve the `// Numeric NIPs` and `// Hexadecimal NIPs` section comments
### NIP_TITLES record
@@ -30,10 +30,27 @@ Read the current file, then:
- Keep existing entries that still match
### DEPRECATED_NIPS array
-- Sync with upstream: add NIPs marked `deprecated`, remove ones no longer deprecated
+- Sync with upstream: add NIPs marked `unrecommended`/`deprecated`, remove ones no longer deprecated
- Keep `as const` assertion
-## Step 3: Update `src/constants/kinds.ts`
+## Step 3: Update `src/lib/nip-icons.ts`
+
+Read the current file. The `NIP_METADATA` record provides icons, short names, and descriptions for each NIP — used by NIPBadge and NipsViewer.
+
+### For every new NIP added in Step 2:
+- Add a corresponding entry to `NIP_METADATA` with: `id` (string, matches the NIP identifier), `name` (short), `description`, `icon` (lucide-react), and `deprecated` if applicable
+- All keys and `id` values are strings (e.g., `"01"`, `"5A"`, `"A0"`)
+- Pick an icon from existing imports; add new imports if needed
+- Place in correct position (numeric keys first, then hex keys sorted)
+
+### For deprecated status changes:
+- Add or remove the `deprecated: true` field to match upstream
+
+### Preserve existing entries:
+- Never change icons on existing entries
+- Only update name/description if upstream changed
+
+## Step 4: Update `src/constants/kinds.ts`
Read the current file, then apply changes carefully.
@@ -57,13 +74,14 @@ Read the current file, then apply changes carefully.
- If the NIP reference changed, update the `nip` field
- **Never** change the `icon` field on existing entries
-## Step 4: Cross-reference validation
+## Step 5: Cross-reference validation
-- Every `nip` field in `EVENT_KINDS` should exist in `VALID_NIPS` (except empty strings `""` and external specs like `"BUD-03"`, `"AMB"`, `"85"`)
+- Every `nip` field in `EVENT_KINDS` should exist in `VALID_NIPS` (except empty strings `""` and external specs like `"BUD-03"`, `"AMB"`, `"Marmot"`)
- Every NIP in `DEPRECATED_NIPS` should also be in `VALID_NIPS`
+- Every NIP in `VALID_NIPS` should have a corresponding entry in `NIP_METADATA` (`src/lib/nip-icons.ts`)
- Flag and fix any inconsistencies
-## Step 5: Verify
+## Step 6: Verify
```bash
npm run lint && npm run test:run && npm run build
@@ -71,10 +89,11 @@ npm run lint && npm run test:run && npm run build
Fix any lint/type/build issues before reporting.
-## Step 6: Report
+## Step 7: Report
Summarize:
- NIPs added / removed / title-updated
+- NIP icons added / updated in `nip-icons.ts`
- Kinds added / updated (with icon choices explained for new ones)
- Inconsistencies found and resolved
- Verification results (lint/test/build)
diff --git a/src/components/NIPBadge.tsx b/src/components/NIPBadge.tsx
index 14ed9a9..e05dd17 100644
--- a/src/components/NIPBadge.tsx
+++ b/src/components/NIPBadge.tsx
@@ -1,6 +1,6 @@
import { getNIPInfo } from "../lib/nip-icons";
import { useAddWindow } from "@/core/state";
-import { isNipDeprecated } from "@/constants/nips";
+import { isNipDeprecated, isValidNip } from "@/constants/nips";
import { getCommunityNipForNipId } from "@/constants/kinds";
export interface NIPBadgeProps {
@@ -26,6 +26,7 @@ export function NIPBadge({
const description =
nipInfo?.description || `Nostr Implementation Possibility ${nipNumber}`;
const isDeprecated = isNipDeprecated(nipNumber);
+ const isExternal = !isValidNip(nipNumber);
const communityNip = getCommunityNipForNipId(nipNumber);
@@ -48,6 +49,18 @@ export function NIPBadge({
);
};
+ // External specs (Marmot, BUD-03, etc.) render as non-interactive labels
+ if (isExternal && !communityNip) {
+ return (
+
+ {nipNumber}
+
+ );
+ }
+
return (
= {
nip: "71",
icon: Video,
},
+ 24: {
+ kind: 24,
+ name: "Public Message",
+ description: "Public Message",
+ nip: "A4",
+ icon: MessageSquare,
+ },
// References (NKBIP-03) - External spec, commented out
// 30: {
@@ -789,6 +797,13 @@ export const EVENT_KINDS: Record = {
nip: "51",
icon: Users,
},
+ 10011: {
+ kind: 10011,
+ name: "External Identities",
+ description: "External Identities",
+ nip: "39",
+ icon: UserCheck,
+ },
10012: {
kind: 10012,
name: "Favorite Relay List",
@@ -842,7 +857,7 @@ export const EVENT_KINDS: Record = {
kind: 10051,
name: "KeyPackage Relays",
description: "KeyPackage Relays List",
- nip: "EE",
+ nip: "Marmot",
icon: Key,
},
10040: {
@@ -901,13 +916,13 @@ export const EVENT_KINDS: Record = {
nip: "",
icon: WandSparkles,
},
- // 10312: {
- // kind: 10312,
- // name: "Room Presence",
- // description: "Room Presence",
- // nip: "53",
- // icon: Users,
- // },
+ 10312: {
+ kind: 10312,
+ name: "Room Presence",
+ description: "Room Presence",
+ nip: "53",
+ icon: Users,
+ },
// 10377: {
// kind: 10377,
// name: "Proxy Announce",
@@ -934,17 +949,31 @@ export const EVENT_KINDS: Record = {
13534: {
kind: 13534,
name: "Relay Members",
- description: "Relay membership list",
+ description: "Membership Lists",
nip: "43",
icon: Users,
},
- // 17375: {
- // kind: 17375,
- // name: "Cashu Wallet Event",
- // description: "Cashu Wallet Event",
- // nip: "60",
- // icon: Wallet,
+ 15128: {
+ kind: 15128,
+ name: "Nsite Manifest",
+ description: "Root nsite manifest",
+ nip: "5A",
+ icon: Globe,
+ },
+ // 14388: {
+ // kind: 14388,
+ // name: "Sound Effect List",
+ // description: "User Sound Effect Lists",
+ // nip: "Corny Chat",
+ // icon: Music,
// },
+ 17375: {
+ kind: 17375,
+ name: "Cashu Wallet Event",
+ description: "Cashu Wallet Event",
+ nip: "60",
+ icon: Wallet,
+ },
// 21000: {
// kind: 21000,
// name: "Lightning Pub RPC",
@@ -1124,6 +1153,13 @@ export const EVENT_KINDS: Record = {
nip: "51",
icon: Video,
},
+ 30006: {
+ kind: 30006,
+ name: "Picture Set",
+ description: "Picture sets",
+ nip: "51",
+ icon: Image,
+ },
30007: {
kind: 30007,
name: "Kind Mute Set",
@@ -1141,7 +1177,7 @@ export const EVENT_KINDS: Record = {
30009: {
kind: 30009,
name: "Badge",
- description: "Badge",
+ description: "Badge Definition",
nip: "58",
icon: Award,
},
@@ -1218,7 +1254,7 @@ export const EVENT_KINDS: Record = {
30063: {
kind: 30063,
name: "App Release",
- description: "Application release with version and files",
+ description: "Release artifact sets",
nip: "51",
icon: Package,
},
@@ -1257,7 +1293,7 @@ export const EVENT_KINDS: Record = {
30267: {
kind: 30267,
name: "App Collection",
- description: "Curated collection of applications",
+ description: "App curation sets",
nip: "51",
icon: BookHeart,
},
@@ -1271,21 +1307,21 @@ export const EVENT_KINDS: Record = {
30382: {
kind: 30382,
name: "User Assertion",
- description: "Trusted Assertion: User",
+ description: "User Trusted Assertion",
nip: "85",
icon: ShieldCheck,
},
30383: {
kind: 30383,
name: "Event Assertion",
- description: "Trusted Assertion: Event",
+ description: "Event Trusted Assertion",
nip: "85",
icon: ShieldCheck,
},
30384: {
kind: 30384,
name: "Address Assertion",
- description: "Trusted Assertion: Addressable Event",
+ description: "Addressable Trusted Assertion",
nip: "85",
icon: ShieldCheck,
},
@@ -1425,35 +1461,56 @@ export const EVENT_KINDS: Record = {
31989: {
kind: 31989,
name: "Recommendation",
- description: "Application Recommendation",
+ description: "Handler recommendation",
nip: "89",
icon: Star,
},
31990: {
kind: 31990,
- name: "Application",
- description: "Application Definition",
+ name: "Handler",
+ description: "Handler information",
nip: "89",
icon: Package,
},
32267: {
kind: 32267,
name: "App",
- description: "Application metadata with platforms and screenshots",
+ description: "Software Application",
nip: "",
icon: Package,
},
+ // 32388: {
+ // kind: 32388,
+ // name: "Room Favorites",
+ // description: "User Room Favorites",
+ // nip: "Corny Chat",
+ // icon: Star,
+ // },
+ // 33388: {
+ // kind: 33388,
+ // name: "High Scores",
+ // description: "High Scores",
+ // nip: "Corny Chat",
+ // icon: Star,
+ // },
+ 34128: {
+ kind: 34128,
+ name: "Legacy Nsite",
+ description: "Legacy nsite manifest (deprecated)",
+ nip: "5A",
+ icon: Globe,
+ },
34235: {
kind: 34235,
name: "Video",
- description: "Horizontal Video (legacy)",
+ description: "Addressable Video Event",
nip: "71",
icon: Video,
},
34236: {
kind: 34236,
name: "Short Video",
- description: "Vertical Video (legacy)",
+ description: "Addressable Short Video Event",
nip: "71",
icon: Video,
},
@@ -1464,6 +1521,13 @@ export const EVENT_KINDS: Record = {
nip: "",
icon: ListMusic,
},
+ // 34388: {
+ // kind: 34388,
+ // name: "Sound Effects",
+ // description: "Sound Effects",
+ // nip: "Corny Chat",
+ // icon: Music,
+ // },
34550: {
kind: 34550,
name: "Community",
@@ -1471,6 +1535,13 @@ export const EVENT_KINDS: Record = {
nip: "72",
icon: Users,
},
+ 35128: {
+ kind: 35128,
+ name: "Named Nsite",
+ description: "Named nsite manifest",
+ nip: "5A",
+ icon: Globe,
+ },
36787: {
kind: 36787,
name: "Music Track",
diff --git a/src/constants/nips.ts b/src/constants/nips.ts
index 4d87190..e277798 100644
--- a/src/constants/nips.ts
+++ b/src/constants/nips.ts
@@ -5,7 +5,7 @@
/**
* Deprecated NIPs that are no longer recommended for use
*/
-export const DEPRECATED_NIPS = ["04", "08", "26", "96"] as const;
+export const DEPRECATED_NIPS = ["04", "08", "26", "96", "EE"] as const;
export const VALID_NIPS = [
// Numeric NIPs
@@ -79,6 +79,7 @@ export const VALID_NIPS = [
"77",
"78",
"84",
+ "85",
"86",
"87",
"88",
@@ -90,8 +91,10 @@ export const VALID_NIPS = [
"98",
"99",
// Hexadecimal NIPs
+ "5A",
"7D",
"A0",
+ "A4",
"B0",
"B7",
"BE",
@@ -177,6 +180,7 @@ export const NIP_TITLES: Record = {
"78": "Application-specific data",
"7D": "Threads",
"84": "Highlights",
+ "85": "Trusted Assertions",
"86": "Relay Management API",
"87": "Ecash Mint Discoverability",
"88": "Polls",
@@ -187,7 +191,9 @@ export const NIP_TITLES: Record = {
"96": "HTTP File Storage Integration",
"98": "HTTP Auth",
"99": "Classified Listings",
+ "5A": "Pubkey Static Websites",
A0: "Voice Messages",
+ A4: "Public Messages",
B0: "Web Bookmarks",
B7: "Blossom",
BE: "Nostr BLE Communications Protocol",
@@ -207,6 +213,10 @@ export function getNipTitle(nipId: string): string {
return NIP_TITLES[nipId] || `NIP-${nipId}`;
}
+export function isValidNip(nipId: string): boolean {
+ return VALID_NIPS.includes(nipId as NipId);
+}
+
export function isNipDeprecated(nipId: string): boolean {
return DEPRECATED_NIPS.includes(nipId as any);
}
diff --git a/src/lib/nip-icons.ts b/src/lib/nip-icons.ts
index 1f0b0c3..8d4a7db 100644
--- a/src/lib/nip-icons.ts
+++ b/src/lib/nip-icons.ts
@@ -1,6 +1,6 @@
/**
* NIP Icon Mapping
- * Maps NIP numbers to Lucide icons for visual representation
+ * Maps NIP identifiers to Lucide icons for visual representation
*/
import {
@@ -46,539 +46,506 @@ import {
} from "lucide-react";
export interface NIPInfo {
- number: number;
+ id: string;
name: string;
description: string;
icon: LucideIcon;
deprecated?: boolean;
}
-export const NIP_METADATA: Record = {
+export const NIP_METADATA: Record = {
// Core Protocol
"01": {
- number: 1,
+ id: "01",
name: "Basic Protocol",
description: "Basic protocol flow description",
icon: FileText,
},
"02": {
- number: 2,
+ id: "02",
name: "Follow List",
description: "Contact list and petnames",
icon: Users,
},
"03": {
- number: 3,
+ id: "03",
name: "OpenTimestamps Attestations for Events",
description: "A proof of any event",
icon: Signature,
},
"04": {
- number: 4,
+ id: "04",
name: "Encrypted DMs",
description: "Encrypted direct messages",
icon: Mail,
deprecated: true,
},
"05": {
- number: 5,
+ id: "05",
name: "Mapping Nostr keys to DNS",
description: "Mapping Nostr keys to DNS-based internet identifiers",
icon: Globe,
},
"06": {
- number: 6,
+ id: "06",
name: "Key Derivation",
description: "Basic key derivation from mnemonic seed phrase",
icon: Key,
},
"07": {
- number: 7,
+ id: "07",
name: "window.nostr",
description: "window.nostr capability for web browsers",
icon: Globe,
},
"08": {
- number: 8,
+ id: "08",
name: "Mentions",
description: "Handling mentions",
icon: Tag,
deprecated: true,
},
"09": {
- number: 9,
+ id: "09",
name: "Event Deletion",
description: "Event deletion",
icon: AlertCircle,
},
- 10: {
- number: 10,
+ "10": {
+ id: "10",
name: "Conventions",
description: "Conventions for clients' use of e and p tags",
icon: Tag,
},
- 11: {
- number: 11,
+ "11": {
+ id: "11",
name: "Relay Info",
description: "Relay information document",
icon: Server,
},
- 13: {
- number: 13,
+ "13": {
+ id: "13",
name: "Proof of Work",
description: "Proof of work",
icon: Zap,
},
- 14: {
- number: 14,
+ "14": {
+ id: "14",
name: "Subject Tag",
description: "Subject tag in text events",
icon: Tag,
},
- 15: {
- number: 15,
+ "15": {
+ id: "15",
name: "Marketplace",
description: "Marketplace (for resilient marketplaces)",
icon: ShoppingCart,
},
- 17: {
- number: 17,
+ "17": {
+ id: "17",
name: "Private DMs",
description: "Private Direct Messages",
icon: Lock,
},
- 18: { number: 18, name: "Reposts", description: "Reposts", icon: Share2 },
- 19: {
- number: 19,
+ "18": { id: "18", name: "Reposts", description: "Reposts", icon: Share2 },
+ "19": {
+ id: "19",
name: "bech32 Entities",
description: "bech32-encoded entities",
icon: Hash,
},
- 21: {
- number: 21,
+ "21": {
+ id: "21",
name: "nostr: URI",
description: "nostr: URI scheme",
icon: Link,
},
- 22: {
- number: 22,
+ "22": {
+ id: "22",
name: "Comment",
description: "Comment",
icon: MessageSquare,
},
- 23: {
- number: 23,
+ "23": {
+ id: "23",
name: "Long-form",
description: "Long-form content",
icon: FileText,
},
- 24: {
- number: 24,
+ "24": {
+ id: "24",
name: "Extra Metadata",
description: "Extra metadata fields and tags",
icon: Tag,
},
- 25: { number: 25, name: "Reactions", description: "Reactions", icon: Heart },
- 26: {
- number: 26,
+ "25": { id: "25", name: "Reactions", description: "Reactions", icon: Heart },
+ "26": {
+ id: "26",
name: "Delegated Signing",
description: "Delegated event signing",
icon: Key,
deprecated: true,
},
- 27: {
- number: 27,
+ "27": {
+ id: "27",
name: "Text Note References",
description: "Text note references",
icon: Link,
},
- 28: {
- number: 28,
+ "28": {
+ id: "28",
name: "Public Chat",
description: "Public chat",
icon: MessageSquare,
},
- 29: {
- number: 29,
+ "29": {
+ id: "29",
name: "Relay Groups",
description: "Relay-based groups",
icon: Users,
},
- 30: {
- number: 30,
+ "30": {
+ id: "30",
name: "Custom Emoji",
description: "Custom emoji",
icon: Gift,
},
- 31: {
- number: 31,
+ "31": {
+ id: "31",
name: "Unknown Events",
description: "Dealing with unknown event kinds",
icon: AlertCircle,
},
- 32: { number: 32, name: "Labeling", description: "Labeling", icon: Tag },
- 34: { number: 34, name: "Git", description: "git stuff", icon: GitBranch },
- 35: { number: 35, name: "Torrents", description: "Torrents", icon: Share2 },
- 36: {
- number: 36,
+ "32": { id: "32", name: "Labeling", description: "Labeling", icon: Tag },
+ "34": { id: "34", name: "Git", description: "git stuff", icon: GitBranch },
+ "35": { id: "35", name: "Torrents", description: "Torrents", icon: Share2 },
+ "36": {
+ id: "36",
name: "Sensitive Content",
description: "Sensitive content warnings",
icon: Eye,
},
- 37: {
- number: 37,
+ "37": {
+ id: "37",
name: "Draft Events",
description: "Draft Events",
icon: FileText,
},
- 38: {
- number: 38,
+ "38": {
+ id: "38",
name: "User Status",
description: "User statuses",
icon: Flag,
},
- 39: {
- number: 39,
+ "39": {
+ id: "39",
name: "External Identity",
description: "External identities in profiles",
icon: Globe,
},
- 40: {
- number: 40,
+ "40": {
+ id: "40",
name: "Expiration",
description: "Expiration timestamp",
icon: Calendar,
},
- 42: {
- number: 42,
+ "42": {
+ id: "42",
name: "Authentication",
description: "Authentication of clients to relays",
icon: Shield,
},
- 43: {
- number: 43,
+ "43": {
+ id: "43",
name: "Relay Access",
description: "Fast Authentication and Relay Access",
icon: Server,
},
- 44: {
- number: 44,
+ "44": {
+ id: "44",
name: "Encrypted Payloads",
description: "Encrypted Payloads (Versioned)",
icon: Lock,
},
- 45: {
- number: 45,
+ "45": {
+ id: "45",
name: "Event Counts",
description: "Counting results",
icon: Hash,
},
- 46: {
- number: 46,
+ "46": {
+ id: "46",
name: "Remote Signing",
description: "Nostr connect protocol",
icon: Key,
},
- 47: {
- number: 47,
+ "47": {
+ id: "47",
name: "Wallet Connect",
description: "Wallet connect",
icon: Wallet,
},
- 48: { number: 48, name: "Proxy Tags", description: "Proxy tags", icon: Tag },
- 49: {
- number: 49,
+ "48": { id: "48", name: "Proxy Tags", description: "Proxy tags", icon: Tag },
+ "49": {
+ id: "49",
name: "Private Key Encryption",
description: "Private key encryption",
icon: Lock,
},
- 50: {
- number: 50,
+ "50": {
+ id: "50",
name: "Search",
description: "Search capability",
icon: Search,
},
- 51: { number: 51, name: "Lists", description: "Lists", icon: Filter },
- 52: {
- number: 52,
+ "51": { id: "51", name: "Lists", description: "Lists", icon: Filter },
+ "52": {
+ id: "52",
name: "Calendar Events",
description: "Calendar Events",
icon: Calendar,
},
- 53: {
- number: 53,
+ "53": {
+ id: "53",
name: "Live Activities",
description: "Live Activities",
icon: Radio,
},
- 54: { number: 54, name: "Wiki", description: "Wiki", icon: FileText },
- 55: {
- number: 55,
+ "54": { id: "54", name: "Wiki", description: "Wiki", icon: FileText },
+ "55": {
+ id: "55",
name: "Android Signer",
description: "Android Signer Application",
icon: Key,
},
- 56: { number: 56, name: "Reporting", description: "Reporting", icon: Flag },
- 57: {
- number: 57,
+ "56": { id: "56", name: "Reporting", description: "Reporting", icon: Flag },
+ "57": {
+ id: "57",
name: "Lightning Zaps",
description: "Lightning zaps",
icon: Zap,
},
- 58: { number: 58, name: "Badges", description: "Badges", icon: Star },
- 59: { number: 59, name: "Gift Wrap", description: "Gift Wrap", icon: Gift },
- 60: {
- number: 60,
+ "58": { id: "58", name: "Badges", description: "Badges", icon: Star },
+ "59": { id: "59", name: "Gift Wrap", description: "Gift Wrap", icon: Gift },
+ "60": {
+ id: "60",
name: "Cashu Wallet",
description: "Cashu Wallet",
icon: Wallet,
},
- 61: { number: 61, name: "Nutzaps", description: "Nutzaps", icon: Zap },
- 62: {
- number: 62,
+ "61": { id: "61", name: "Nutzaps", description: "Nutzaps", icon: Zap },
+ "62": {
+ id: "62",
name: "Request to Vanish",
description: "Request to Vanish",
icon: Eye,
},
- 64: { number: 64, name: "Chess", description: "Chess (PGN)", icon: Gamepad2 },
- 65: {
- number: 65,
+ "64": { id: "64", name: "Chess", description: "Chess (PGN)", icon: Gamepad2 },
+ "65": {
+ id: "65",
name: "Relay List",
description: "Relay list metadata",
icon: Server,
},
- 66: {
- number: 66,
+ "66": {
+ id: "66",
name: "Relay Discovery",
description: "Relay Discovery",
icon: Compass,
},
- 68: {
- number: 68,
+ "68": {
+ id: "68",
name: "Picture-first",
description: "Picture-first feeds",
icon: Image,
},
- 69: {
- number: 69,
+ "69": {
+ id: "69",
name: "P2P Order",
description: "Peer-to-peer Order events",
icon: ShoppingCart,
},
- 70: {
- number: 70,
+ "70": {
+ id: "70",
name: "Protected Events",
description: "Protected Events",
icon: Shield,
},
- 71: {
- number: 71,
+ "71": {
+ id: "71",
name: "Video Events",
description: "Video Events",
icon: Video,
},
- 72: {
- number: 72,
+ "72": {
+ id: "72",
name: "Moderation",
description: "Moderated communities",
icon: Shield,
},
- 73: {
- number: 73,
+ "73": {
+ id: "73",
name: "External Content IDs",
description: "External Content IDs",
icon: Link,
},
- 75: { number: 75, name: "Zap Goals", description: "Zap Goals", icon: Zap },
- 77: {
- number: 77,
+ "75": { id: "75", name: "Zap Goals", description: "Zap Goals", icon: Zap },
+ "77": {
+ id: "77",
name: "Negentropy",
description: "Negentropy Protocol Sync",
icon: Server,
},
- 78: {
- number: 78,
+ "78": {
+ id: "78",
name: "App Data",
description: "Application-specific data",
icon: Database,
},
- 84: {
- number: 84,
+ "84": {
+ id: "84",
name: "Highlights",
description: "Highlights",
icon: Bookmark,
},
- 86: {
- number: 86,
+ "85": {
+ id: "85",
+ name: "Trusted Assertions",
+ description: "Trusted Assertions",
+ icon: Shield,
+ },
+ "86": {
+ id: "86",
name: "Relay Management",
description: "Relay Management API",
icon: Server,
},
- 87: {
- number: 87,
+ "87": {
+ id: "87",
name: "Ecash Mints",
description: "Ecash Mint Discoverability",
icon: Coins,
},
- 88: { number: 88, name: "Polls", description: "Polls", icon: Filter },
- 89: {
- number: 89,
+ "88": { id: "88", name: "Polls", description: "Polls", icon: Filter },
+ "89": {
+ id: "89",
name: "App Handlers",
description: "Recommended application handlers",
icon: Package,
},
- 90: {
- number: 90,
+ "90": {
+ id: "90",
name: "Data Vending",
description: "Data Vending Machines",
icon: Database,
},
- 92: {
- number: 92,
+ "92": {
+ id: "92",
name: "Media Attachments",
description: "Media Attachments",
icon: Image,
},
- 94: {
- number: 94,
+ "94": {
+ id: "94",
name: "File Metadata",
description: "File metadata",
icon: Image,
},
- 96: {
- number: 96,
+ "96": {
+ id: "96",
name: "HTTP File Storage",
description: "HTTP File Storage Integration",
icon: Server,
deprecated: true,
},
- 98: {
- number: 98,
+ "98": {
+ id: "98",
name: "HTTP Auth",
description: "HTTP authentication",
icon: Lock,
},
- 99: {
- number: 99,
+ "99": {
+ id: "99",
name: "Classified Listings",
description: "Classified listings",
icon: Tag,
},
- // Hex NIPs (A0-EE)
+ // Hex NIPs (5A-EE)
+ "5A": {
+ id: "5A",
+ name: "Static Websites",
+ description: "Pubkey Static Websites",
+ icon: Globe,
+ },
+ "7D": {
+ id: "7D",
+ name: "Threads",
+ description: "Threads",
+ icon: MessageSquare,
+ },
A0: {
- number: 0xa0,
+ id: "A0",
name: "Voice Messages",
description: "Voice Messages",
icon: Music,
},
+ A4: {
+ id: "A4",
+ name: "Public Messages",
+ description: "Public Messages",
+ icon: MessageSquare,
+ },
B0: {
- number: 0xb0,
+ id: "B0",
name: "Web Bookmarks",
description: "Web Bookmarks",
icon: Bookmark,
},
- B7: { number: 0xb7, name: "Blossom", description: "Blossom", icon: Package },
+ B7: { id: "B7", name: "Blossom", description: "Blossom", icon: Package },
BE: {
- number: 0xbe,
+ id: "BE",
name: "BLE",
description: "BLE Communications",
icon: Radio,
},
C0: {
- number: 0xc0,
+ id: "C0",
name: "Code Snippets",
description: "Code Snippets",
icon: Code,
},
C7: {
- number: 0xc7,
+ id: "C7",
name: "Chats",
description: "Chats",
icon: MessageSquare,
},
EE: {
- number: 0xee,
+ id: "EE",
name: "E2EE MLS",
description: "E2EE Messaging (MLS)",
icon: Lock,
- },
- "7D": {
- number: 0x7d,
- name: "Threads",
- description: "Threads",
- icon: MessageSquare,
+ deprecated: true,
},
};
/**
- * Get NIP metadata by number (handles both decimal and hex)
+ * Get NIP metadata by identifier (handles both string IDs and numeric lookups)
*/
-export function getNIPInfo(nipNumber: number | string): NIPInfo | undefined {
+export function getNIPInfo(nipId: number | string): NIPInfo | undefined {
+ const key = typeof nipId === "string" ? nipId : String(nipId);
+
// Try direct lookup
- if (NIP_METADATA[nipNumber]) {
- return NIP_METADATA[nipNumber];
+ if (NIP_METADATA[key]) {
+ return NIP_METADATA[key];
}
// Try hex conversion for numbers > 99
- if (typeof nipNumber === "number" && nipNumber > 99) {
- const hexKey = nipNumber.toString(16).toUpperCase();
+ if (typeof nipId === "number" && nipId > 99) {
+ const hexKey = nipId.toString(16).toUpperCase();
return NIP_METADATA[hexKey];
}
return undefined;
}
-
-/**
- * Get all supported NIPs with their metadata, excluding deprecated ones
- */
-export function getSupportedNIPsInfo(
- nipNumbers: number[],
- includeDeprecated: boolean = false,
-): (NIPInfo | { number: number; name: string; icon: LucideIcon })[] {
- return nipNumbers
- .map((num) => {
- const info = getNIPInfo(num);
- if (info) {
- // Skip deprecated NIPs unless explicitly included
- if (!includeDeprecated && info.deprecated) {
- return null;
- }
- return info;
- }
- // Fallback for unknown NIPs
- return {
- number: num,
- name: `NIP-${num}`,
- icon: FileText,
- };
- })
- .filter(
- (
- nip,
- ): nip is NIPInfo | { number: number; name: string; icon: LucideIcon } =>
- nip !== null,
- );
-}
-
-/**
- * Group NIPs by a single consolidated category
- * For relay viewer, we show all NIPs in one list
- */
-export function groupNIPsByCategory(
- nipNumbers: number[],
-): Record {
- const grouped: Record = {
- "Supported NIPs": [],
- };
-
- nipNumbers.forEach((num) => {
- const info = getNIPInfo(num);
- // Skip deprecated NIPs
- if (info && !info.deprecated) {
- grouped["Supported NIPs"].push(info);
- }
- });
-
- return grouped;
-}