diff --git a/src/components/ChatViewer.tsx b/src/components/ChatViewer.tsx
index f2b2061..3ffc805 100644
--- a/src/components/ChatViewer.tsx
+++ b/src/components/ChatViewer.tsx
@@ -181,9 +181,15 @@ const MessageItem = memo(function MessageItem({
// Zap messages have special styling with gradient border
if (message.type === "zap") {
const zapRequest = message.event ? getZapRequest(message.event) : null;
+ // For NIP-57 zaps, reply target is in the zap request's e-tag
+ // For NIP-61 nutzaps, reply target is already in message.replyTo
+ const zapReplyTo =
+ message.replyTo ||
+ zapRequest?.tags.find((t) => t[0] === "e")?.[1] ||
+ undefined;
return (
-
+
+ {zapReplyTo && (
+
+ )}
{message.content && (
)}
diff --git a/src/lib/chat/adapters/nip-29-adapter.ts b/src/lib/chat/adapters/nip-29-adapter.ts
index f576fef..1bd24f5 100644
--- a/src/lib/chat/adapters/nip-29-adapter.ts
+++ b/src/lib/chat/adapters/nip-29-adapter.ts
@@ -676,22 +676,29 @@ export class Nip29Adapter extends ChatProtocolAdapter {
const pTag = event.tags.find((t) => t[0] === "p");
const recipient = pTag?.[1] || "";
- // Amount is sum of proof amounts from the proof tag
- // proof tag format: ["proof", "
"]
- const proofTag = event.tags.find((t) => t[0] === "proof");
+ // Reply target is the e-tag (the event being nutzapped)
+ const eTag = event.tags.find((t) => t[0] === "e");
+ const replyTo = eTag?.[1];
+
+ // Amount is sum of proof amounts from all proof tags
+ // NIP-61 allows multiple proof tags, each containing a JSON-encoded Cashu proof
let amount = 0;
- if (proofTag?.[1]) {
- try {
- const proofs = JSON.parse(proofTag[1]);
- if (Array.isArray(proofs)) {
- amount = proofs.reduce(
- (sum: number, proof: { amount?: number }) =>
- sum + (proof.amount || 0),
- 0,
- );
+ for (const tag of event.tags) {
+ if (tag[0] === "proof" && tag[1]) {
+ try {
+ const proof = JSON.parse(tag[1]);
+ // Proof can be a single object or an array of proofs
+ if (Array.isArray(proof)) {
+ amount += proof.reduce(
+ (sum: number, p: { amount?: number }) => sum + (p.amount || 0),
+ 0,
+ );
+ } else if (typeof proof === "object" && proof.amount) {
+ amount += proof.amount;
+ }
+ } catch {
+ // Invalid proof JSON, skip this tag
}
- } catch {
- // Invalid proof JSON, amount stays 0
}
}
@@ -709,6 +716,7 @@ export class Nip29Adapter extends ChatProtocolAdapter {
content: comment,
timestamp: event.created_at,
type: "zap", // Render the same as zaps
+ replyTo,
protocol: "nip-29",
metadata: {
encrypted: false,