Exigence du d-tag pour les événements adressables Nostr
Problème
Lors de la publication d'événements remplaçables paramétrés (Kind 30000-39999, y compris les événements vidéo NIP-71 Kind 34236), les événements apparaissent comme des doublons sur le relay au lieu de se remplacer les uns les autres. Le même contenu s'affiche plusieurs fois pour le même utilisateur.
Contexte / Conditions de déclenchement
- Publication d'événements Kind 30000+ (événements remplaçables paramétrés)
- La même vidéo/contenu apparaît plusieurs fois dans le fil de l'utilisateur
- Les événements ont les mêmes pubkey, kind et contenu mais des ID d'événement différents
- Le relay retourne plusieurs événements alors qu'on en attend un
- Utilisation de NIP-71 (Kind 34236) pour les événements vidéo
- Utilisation de NIP-23 (Kind 30023) pour le contenu long format
- Tout type d'événement adressable affichant des doublons
Solution
Cause racine
Les événements remplaçables paramétrés (Kind 30000-39999) nécessitent un tag d pour être adressables. La combinaison pubkey + kind + valeur du d-tag forme l'adresse unique. Sans tag d, le relay traite chaque événement comme un événement distinct non remplaçable.
Correctif
Toujours inclure un tag d avec un identifiant unique pour le contenu :
// CORRECT - a un d tag, sera remplaçable
const event = {
kind: 34236, // NIP-71 video
pubkey: userPubkey,
content: "Video description",
tags: [
["d", videoId], // REQUIS pour l'adressabilité
["title", "My Video"],
["url", "https://..."],
// ... autres tags
]
};
// INCORRECT - d tag manquant, crée un nouvel événement à chaque fois
const badEvent = {
kind: 34236,
pubkey: userPubkey,
content: "Video description",
tags: [
["title", "My Video"], // Pas de d tag!
["url", "https://..."],
]
};
Pour les événements vidéo NIP-71
Utiliser l'identifiant unique de la vidéo (vine_id, video_id, etc.) comme valeur du d-tag :
tags.push(["d", video.id]);
Nettoyage des doublons existants
- Récupérer tous les événements pour la pubkey :
{ kinds: [34236], authors: [pubkey] } - Identifier les événements sans d-tags (ce sont les doublons)
- Publier des événements de suppression NIP-09 (Kind 5) référençant les mauvais ID d'événement
- Republier avec les d-tags corrects
Vérification
Après ajout du d-tag :
- Publier le même contenu deux fois
- Interroger le relay pour les événements avec cette pubkey+kind
- Devrait retourner UN SEUL événement (le plus récent)
- L'ID d'événement changera mais l'adresse du d-tag reste constante
// Vérifier l'absence de doublons
const events = await ndk.fetchEvents({ kinds: [34236], authors: [pubkey] });
const byDTag = new Map();
for (const e of events) {
const d = e.tags.find(t => t[0] === 'd')?.[1];
if (!byDTag.has(d)) byDTag.set(d, []);
byDTag.get(d).push(e);
}
// Chaque valeur de d-tag devrait avoir exactement 1 événement
for (const [d, evts] of byDTag) {
if (evts.length > 1) console.log(`Duplicate: d=${d} has ${evts.length} events`);
}
Exemple
Avant le correctif - les événements sans d-tag créent des doublons :
Event 1: id=abc123, kind=34236, tags=[["title", "My Video"]]
Event 2: id=def456, kind=34236, tags=[["title", "My Video"]] // Doublon!
Après le correctif - les événements avec d-tag se remplacent les uns les autres :
Event 1: id=abc123, kind=34236, tags=[["d", "video-001"], ["title", "My Video"]]
// Republication du même contenu...
Event 2: id=xyz789, kind=34236, tags=[["d", "video-001"], ["title", "My Video Updated"]]
// Event 1 est remplacé, seul Event 2 existe
Notes
- La valeur du d-tag devrait être stable entre les republications (utiliser l'ID du contenu, pas une valeur aléatoire)
- Une chaîne vide
["d", ""]est valide mais signifie un seul événement de ce kind par pubkey - Les événements remplaçables réguliers (Kind 0, 3, 10000-19999) ne nécessitent pas de d-tag
- Ceci s'applique à TOUS les événements remplaçables paramétrés, pas seulement les vidéos
- La mise en cache frontend peut afficher les anciens doublons même après nettoyage du relay - actualisation complète nécessaire