Revert "feat: Add Badge Awards to chat"

This reverts commits:
- 1686a94 feat: Add Badge Awards (kind 8) to NIP-53 live chat
- 909359f feat: Add Badge Awards (kind 8) to chat as system messages

Badge award rendering in chat will be implemented later.
This keeps the PR focused on Profile Badges (kind 30008) implementation.
This commit is contained in:
Claude
2026-01-17 19:14:56 +00:00
parent 1686a9441e
commit a5e663e5f3
4 changed files with 6 additions and 180 deletions

View File

@@ -35,12 +35,6 @@ import { UserName } from "./nostr/UserName";
import { RichText } from "./nostr/RichText";
import Timestamp from "./Timestamp";
import { ReplyPreview } from "./chat/ReplyPreview";
import { Award } from "lucide-react";
import {
getBadgeName,
getBadgeIdentifier,
getBadgeImageUrl,
} from "@/lib/nip58-helpers";
import { MembersDropdown } from "./chat/MembersDropdown";
import { RelaysDropdown } from "./chat/RelaysDropdown";
import { MessageReactions } from "./chat/MessageReactions";
@@ -204,106 +198,6 @@ type ConversationResult =
| { status: "success"; conversation: Conversation }
| { status: "error"; error: string };
/**
* Parse badge address to extract pubkey and identifier
*/
function parseBadgeAddress(address: string): {
kind: number;
pubkey: string;
identifier: string;
} | null {
const parts = address.split(":");
if (parts.length !== 3) return null;
const kind = parseInt(parts[0], 10);
const pubkey = parts[1];
const identifier = parts[2];
if (isNaN(kind) || !pubkey || identifier === undefined) return null;
return { kind, pubkey, identifier };
}
/**
* BadgeAwardSystemMessage - Renders badge award as system message
* Format: "🏆 username awarded 🏅 badge-name to username(s)"
*/
const BadgeAwardSystemMessage = memo(function BadgeAwardSystemMessage({
message,
badgeAddress,
awardedPubkeys,
}: {
message: Message;
badgeAddress: string;
awardedPubkeys: string[];
}) {
const coordinate = parseBadgeAddress(badgeAddress);
// Fetch the badge definition event
const badgeEvent = use$(
() =>
coordinate
? eventStore.replaceable(
coordinate.kind,
coordinate.pubkey,
coordinate.identifier,
)
: undefined,
[coordinate?.kind, coordinate?.pubkey, coordinate?.identifier],
);
const badgeName = badgeEvent ? getBadgeName(badgeEvent) : null;
const badgeIdentifier = badgeEvent ? getBadgeIdentifier(badgeEvent) : null;
const badgeImageUrl = badgeEvent ? getBadgeImageUrl(badgeEvent) : null;
const displayBadgeName = badgeName || badgeIdentifier || "a badge";
return (
<div className="flex items-center gap-1.5 px-3 py-1 flex-wrap">
<span className="text-xs text-muted-foreground">*</span>
{/* Issuer */}
<UserName
pubkey={message.author}
className="text-xs text-muted-foreground"
/>
<span className="text-xs text-muted-foreground">awarded</span>
{/* Badge Icon */}
{badgeImageUrl ? (
<img
src={badgeImageUrl}
alt={displayBadgeName}
className="size-4 rounded object-cover flex-shrink-0"
loading="lazy"
/>
) : (
<Award className="size-4 text-muted-foreground flex-shrink-0" />
)}
{/* Badge Name */}
<span className="text-xs font-semibold text-muted-foreground">
{displayBadgeName}
</span>
<span className="text-xs text-muted-foreground">to</span>
{/* Recipients */}
{awardedPubkeys.length === 1 ? (
<UserName
pubkey={awardedPubkeys[0]}
className="text-xs text-muted-foreground"
/>
) : (
<span className="text-xs text-muted-foreground">
{awardedPubkeys.length} people
</span>
)}
</div>
);
});
/**
* ComposerReplyPreview - Shows who is being replied to in the composer
*/
@@ -379,20 +273,8 @@ const MessageItem = memo(function MessageItem({
[conversation],
);
// System messages (join/leave/badge-award) have special styling
// System messages (join/leave) have special styling
if (message.type === "system") {
// Badge awards get special rendering
if (message.content === "badge-award" && message.metadata?.badgeAddress) {
return (
<BadgeAwardSystemMessage
message={message}
badgeAddress={message.metadata.badgeAddress}
awardedPubkeys={message.metadata.awardedPubkeys || []}
/>
);
}
// Default system message rendering (join/leave)
return (
<div className="flex items-center px-3 py-1">
<span className="text-xs text-muted-foreground">

View File

@@ -21,7 +21,6 @@ import accountManager from "@/services/accounts";
import { getTagValues } from "@/lib/nostr-utils";
import { normalizeRelayURL } from "@/lib/relay-url";
import { EventFactory } from "applesauce-core/event-factory";
import { getAwardedPubkeys } from "@/lib/nip58-helpers";
/**
* NIP-29 Adapter - Relay-Based Groups
@@ -322,13 +321,12 @@ export class Nip29Adapter extends ChatProtocolAdapter {
console.log(`[NIP-29] Loading messages for ${groupId} from ${relayUrl}`);
// Single filter for all group events:
// kind 8: badge awards (NIP-58)
// kind 9: chat messages
// kind 9000: put-user (admin adds user)
// kind 9001: remove-user (admin removes user)
// kind 9321: nutzaps (NIP-61)
const filter: Filter = {
kinds: [8, 9, 9000, 9001, 9321],
kinds: [9, 9000, 9001, 9321],
"#h": [groupId],
limit: options?.limit || 50,
};
@@ -405,7 +403,7 @@ export class Nip29Adapter extends ChatProtocolAdapter {
// Same filter as loadMessages but with until for pagination
const filter: Filter = {
kinds: [8, 9, 9000, 9001, 9321],
kinds: [9, 9000, 9001, 9321],
"#h": [groupId],
until: before,
limit: 50,
@@ -1058,30 +1056,6 @@ export class Nip29Adapter extends ChatProtocolAdapter {
* Helper: Convert Nostr event to Message
*/
private eventToMessage(event: NostrEvent, conversationId: string): Message {
// Handle badge awards (kind 8) as system messages
if (event.kind === 8) {
const awardedPubkeys = getAwardedPubkeys(event);
const badgeAddress = getTagValues(event, "a")[0]; // Badge definition address
// Content will be set to "badge-award" to trigger special rendering
return {
id: event.id,
conversationId,
author: event.pubkey, // Issuer
content: "badge-award",
timestamp: event.created_at,
type: "system",
protocol: "nip-29",
metadata: {
encrypted: false,
// Store badge info for rendering
badgeAddress,
awardedPubkeys,
},
event,
};
}
// Handle admin events (join/leave) as system messages
if (event.kind === 9000 || event.kind === 9001) {
// Extract the affected user's pubkey from p-tag

View File

@@ -29,8 +29,6 @@ import {
isValidZap,
} from "applesauce-common/helpers/zap";
import { EventFactory } from "applesauce-core/event-factory";
import { getAwardedPubkeys } from "@/lib/nip58-helpers";
import { getTagValues } from "@/lib/nostr-utils";
/**
* NIP-53 Adapter - Live Activity Chat
@@ -261,9 +259,9 @@ export class Nip53Adapter extends ChatProtocolAdapter {
`[NIP-53] Loading messages for ${aTagValue} from ${relays.length} relays`,
);
// Single filter for live chat messages (kind 1311), badge awards (kind 8), and zaps (kind 9735)
// Single filter for live chat messages (kind 1311) and zaps (kind 9735)
const filter: Filter = {
kinds: [8, 1311, 9735],
kinds: [1311, 9735],
"#a": [aTagValue],
limit: options?.limit || 50,
};
@@ -363,7 +361,7 @@ export class Nip53Adapter extends ChatProtocolAdapter {
// Same filter as loadMessages but with until for pagination
const filter: Filter = {
kinds: [8, 1311, 9735],
kinds: [1311, 9735],
"#a": [aTagValue],
until: before,
limit: 50,
@@ -675,30 +673,6 @@ export class Nip53Adapter extends ChatProtocolAdapter {
* Helper: Convert Nostr event to Message
*/
private eventToMessage(event: NostrEvent, conversationId: string): Message {
// Handle badge awards (kind 8) as system messages
if (event.kind === 8) {
const awardedPubkeys = getAwardedPubkeys(event);
const badgeAddress = getTagValues(event, "a")[0]; // Badge definition address
// Content will be set to "badge-award" to trigger special rendering
return {
id: event.id,
conversationId,
author: event.pubkey, // Issuer
content: "badge-award",
timestamp: event.created_at,
type: "system",
protocol: "nip-53",
metadata: {
encrypted: false,
// Store badge info for rendering
badgeAddress,
awardedPubkeys,
},
event,
};
}
// Look for reply e-tags (NIP-10 style)
const eTags = event.tags.filter((t) => t[0] === "e");
// Find the reply tag (has "reply" marker or is the last e-tag without marker)

View File

@@ -5,7 +5,6 @@ import type { NostrEvent } from "./nostr";
* Used for filtering and validating chat-related events
*/
export const CHAT_KINDS = [
8, // NIP-58: Badge awards (system messages)
9, // NIP-29: Group chat messages
9321, // NIP-61: Nutzaps (ecash zaps in groups/live chats)
1311, // NIP-53: Live chat messages
@@ -107,9 +106,6 @@ export interface MessageMetadata {
zapRecipient?: string; // Pubkey of zap recipient
// NIP-61 nutzap-specific metadata
nutzapUnit?: string; // Unit for nutzap amount (sat, usd, eur, etc.)
// Badge award metadata (for type: "system" with content: "badge-award")
badgeAddress?: string; // Badge definition address (30009:pubkey:identifier)
awardedPubkeys?: string[]; // Pubkeys of recipients
}
/**