docs: Fusion et simplification documentation features/
- Fusion tous documents implémentations en features.md - Suppression documents redondants/obsolètes : - final-cleanup-summary.md, storage-encryption.md - storage-improvement-implementation.md, notifications-scope.md - user-profile-implementation.md, filtering-search-implementation.md - article-edit-delete.md, priority1-implementation.md - alby-integration.md, nostr-paywall-implementation.md - technical-doc.md (redondant avec docs/technical.md) - rizful-integration.md (obsolète, remplacé par Alby) - Documentation fidèle au code actuel - Garde zapwall4science-refactoring.md (spécifications) - Garde series-and-media-spec.md (spécifications) - Garde notifications-implementation.md (détails techniques)
This commit is contained in:
parent
9ea4965c05
commit
a099f3c24a
@ -89,4 +89,3 @@ Tous les événements sont loggés avec IDs, timestamps et statuts.
|
|||||||
## Limitations
|
## Limitations
|
||||||
|
|
||||||
**Transferts Lightning automatiques** : Nécessitent un nœud Lightning de la plateforme. Actuellement, les transferts sont loggés dans `lib/automaticTransfer.ts` et peuvent être exécutés manuellement. Les adresses Lightning sont récupérées automatiquement depuis les profils Nostr.
|
**Transferts Lightning automatiques** : Nécessitent un nœud Lightning de la plateforme. Actuellement, les transferts sont loggés dans `lib/automaticTransfer.ts` et peuvent être exécutés manuellement. Les adresses Lightning sont récupérées automatiquement depuis les profils Nostr.
|
||||||
|
|
||||||
|
|||||||
@ -1,145 +0,0 @@
|
|||||||
# Intégration Alby/WebLN pour paiements Lightning
|
|
||||||
|
|
||||||
**Auteur** : Équipe 4NK
|
|
||||||
|
|
||||||
## Objectif
|
|
||||||
|
|
||||||
Remplacer l'intégration Rizful par Alby/WebLN pour les paiements Lightning, permettant une intégration directe avec les portefeuilles Lightning du navigateur sans nécessiter d'API backend.
|
|
||||||
|
|
||||||
## Impacts
|
|
||||||
|
|
||||||
### Utilisateurs
|
|
||||||
- Paiements Lightning facilités via l'extension Alby ou autres portefeuilles WebLN
|
|
||||||
- Pas besoin de compte externe (Rizful) pour recevoir des paiements
|
|
||||||
- Interface de paiement native du navigateur
|
|
||||||
- Vérification des paiements via zap receipts sur Nostr
|
|
||||||
|
|
||||||
### Développeurs
|
|
||||||
- Pas besoin de clé API externe
|
|
||||||
- Pas besoin d'API routes backend pour les paiements
|
|
||||||
- Utilisation du standard WebLN (compatible avec tous les portefeuilles WebLN)
|
|
||||||
- Architecture simplifiée
|
|
||||||
|
|
||||||
### Technique
|
|
||||||
- Service `AlbyService` utilisant le standard WebLN
|
|
||||||
- Vérification des paiements via zap receipts Nostr
|
|
||||||
- Compatible avec Alby et autres portefeuilles WebLN
|
|
||||||
|
|
||||||
## Modifications
|
|
||||||
|
|
||||||
### Nouveaux fichiers
|
|
||||||
|
|
||||||
#### `lib/alby.ts` - Service Alby/WebLN
|
|
||||||
Service principal pour interagir avec les portefeuilles Lightning via WebLN :
|
|
||||||
- `enable()` : Demander l'autorisation à l'utilisateur
|
|
||||||
- `createInvoice()` : Créer une facture Lightning via le portefeuille
|
|
||||||
- `sendPayment()` : Envoyer un paiement via le portefeuille
|
|
||||||
- `checkPaymentStatus()` : Placeholder (vérification via zap receipts)
|
|
||||||
- `waitForPayment()` : Attendre la confirmation via zap receipts
|
|
||||||
|
|
||||||
#### `types/alby.ts` - Types TypeScript
|
|
||||||
Types pour Alby/WebLN :
|
|
||||||
- `AlbyInvoice` : Structure d'une facture Lightning
|
|
||||||
- `AlbyPaymentStatus` : Statut d'un paiement
|
|
||||||
- `AlbyInvoiceRequest` : Requête de création de facture
|
|
||||||
|
|
||||||
### Fichiers modifiés
|
|
||||||
|
|
||||||
#### `lib/payment.ts`
|
|
||||||
- Remplacement de `RizfulService` par `AlbyService`
|
|
||||||
- Utilisation de zap receipts pour la vérification des paiements
|
|
||||||
- Simplification du flux de paiement
|
|
||||||
|
|
||||||
#### `components/PaymentModal.tsx`
|
|
||||||
- Intégration de `AlbyService` pour le paiement
|
|
||||||
- Utilisation de `sendPayment()` pour payer directement via WebLN
|
|
||||||
- Fallback vers URI Lightning si WebLN n'est pas disponible
|
|
||||||
|
|
||||||
#### `components/ArticleCard.tsx`
|
|
||||||
- Mise à jour des types (remplacement de `RizfulInvoice` par `AlbyInvoice`)
|
|
||||||
|
|
||||||
#### `next.config.js`
|
|
||||||
- Suppression des variables d'environnement Rizful
|
|
||||||
|
|
||||||
#### `README.md`
|
|
||||||
- Mise à jour de la documentation pour Alby
|
|
||||||
- Instructions pour installer l'extension Alby
|
|
||||||
|
|
||||||
### Fichiers supprimés
|
|
||||||
|
|
||||||
- `lib/rizful.ts` - Service Rizful (remplacé par `lib/alby.ts`)
|
|
||||||
- `types/rizful.ts` - Types Rizful (remplacé par `types/alby.ts`)
|
|
||||||
- `pages/api/rizful/invoice.ts` - API route Rizful (plus nécessaire)
|
|
||||||
- `pages/api/rizful/payment/[hash].ts` - API route Rizful (plus nécessaire)
|
|
||||||
|
|
||||||
### Flux de paiement avec Alby
|
|
||||||
|
|
||||||
1. **Utilisateur clique sur "Unlock for X sats"**
|
|
||||||
- Vérification de la connexion Nostr
|
|
||||||
- Demande d'activation de WebLN (Alby)
|
|
||||||
- Création d'une facture Lightning via WebLN
|
|
||||||
|
|
||||||
2. **Affichage de la modal de paiement**
|
|
||||||
- Facture Lightning affichée
|
|
||||||
- Option pour payer directement via WebLN (bouton "Pay with Alby")
|
|
||||||
- Option pour copier la facture
|
|
||||||
|
|
||||||
3. **Paiement utilisateur**
|
|
||||||
- Utilisateur paie via son portefeuille WebLN (Alby)
|
|
||||||
- Le portefeuille gère le paiement
|
|
||||||
|
|
||||||
4. **Vérification du paiement**
|
|
||||||
- Polling des zap receipts sur Nostr
|
|
||||||
- Vérification de la signature et du montant
|
|
||||||
- Confirmation du paiement
|
|
||||||
|
|
||||||
5. **Déblocage du contenu**
|
|
||||||
- Une fois le paiement confirmé via zap receipt, chargement du contenu privé
|
|
||||||
- Affichage du contenu complet
|
|
||||||
|
|
||||||
## Modalités de déploiement
|
|
||||||
|
|
||||||
### Prérequis
|
|
||||||
- Extension Alby installée (pour les utilisateurs)
|
|
||||||
- Ou autre portefeuille WebLN compatible
|
|
||||||
|
|
||||||
### Installation pour les utilisateurs
|
|
||||||
|
|
||||||
Les utilisateurs doivent installer l'extension Alby :
|
|
||||||
1. Aller sur [https://getalby.com/](https://getalby.com/)
|
|
||||||
2. Installer l'extension pour leur navigateur (Chrome, Firefox, etc.)
|
|
||||||
3. Créer un compte Alby ou connecter un portefeuille Lightning existant
|
|
||||||
|
|
||||||
### Configuration
|
|
||||||
|
|
||||||
Aucune configuration serveur nécessaire ! Tout fonctionne côté client via WebLN.
|
|
||||||
|
|
||||||
### Déploiement
|
|
||||||
|
|
||||||
Aucun changement dans le processus de déploiement standard. Le code fonctionne entièrement côté client.
|
|
||||||
|
|
||||||
### Sécurité
|
|
||||||
|
|
||||||
- **WebLN** : Standard ouvert et sécurisé pour les portefeuilles Lightning
|
|
||||||
- **Vérification** : Les paiements sont vérifiés via zap receipts Nostr avec signatures cryptographiques
|
|
||||||
- **Pas d'API key** : Plus besoin de gérer des clés API côté serveur
|
|
||||||
|
|
||||||
## Avantages par rapport à Rizful
|
|
||||||
|
|
||||||
1. **Pas de clé API** : Plus besoin de configuration serveur
|
|
||||||
2. **Standard ouvert** : WebLN est un standard, compatible avec plusieurs portefeuilles
|
|
||||||
3. **Meilleure UX** : Intégration native avec le navigateur
|
|
||||||
4. **Décentralisé** : Les utilisateurs gardent le contrôle de leur portefeuille
|
|
||||||
5. **Pas de frais d'API** : Pas de service externe à payer
|
|
||||||
|
|
||||||
## Limitations
|
|
||||||
|
|
||||||
1. **Extension requise** : Les utilisateurs doivent avoir une extension WebLN installée
|
|
||||||
2. **Vérification via zap receipts** : La vérification des paiements dépend des zap receipts sur Nostr (ce qui est normal pour un système Nostr)
|
|
||||||
|
|
||||||
## Points d'amélioration
|
|
||||||
|
|
||||||
1. **Détection automatique** : Améliorer la détection de l'extension WebLN
|
|
||||||
2. **Guide d'installation** : Ajouter un guide d'installation de l'extension pour les utilisateurs
|
|
||||||
3. **Support de plusieurs portefeuilles** : Tester et supporter d'autres portefeuilles WebLN
|
|
||||||
4. **Gestion des erreurs** : Améliorer les messages d'erreur si WebLN n'est pas disponible
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
# Article edit/delete via Nostr events
|
|
||||||
|
|
||||||
**Objectif**
|
|
||||||
Permettre aux auteurs d’éditer ou supprimer leurs articles en publiant des événements Nostr dédiés (update + delete), avec confirmation explicite côté UI.
|
|
||||||
|
|
||||||
**Impacts**
|
|
||||||
- Parcours auteur : édition depuis la liste de mes articles, suppression confirmée avant envoi de l’événement kind 5.
|
|
||||||
- Stockage local : contenu privé ré-encrypté et ré-enregistré pour les mises à jour.
|
|
||||||
- Pas d’impact côté lecteurs (pas de fallback).
|
|
||||||
|
|
||||||
**Modifications**
|
|
||||||
- `lib/articleMutations.ts` : publication update/delete (tags e, replace), réutilisation du stockage chiffré.
|
|
||||||
- `components/UserArticles.tsx`, `components/UserArticlesList.tsx`, `components/UserArticlesEditPanel.tsx` : UI édition/suppression avec confirmation, découpage pour respecter lint/max-lines.
|
|
||||||
- `lib/articleInvoice.ts` : factorisation des tags de preview.
|
|
||||||
|
|
||||||
**Modalités de déploiement**
|
|
||||||
Standard front : build Next.js habituel. Pas de migrations ni dépendances supplémentaires.
|
|
||||||
|
|
||||||
**Modalités d’analyse**
|
|
||||||
- Vérifier qu’un auteur connecté peut éditer puis voir son article mis à jour dans la liste.
|
|
||||||
- Vérifier que la suppression publie l’événement et retire l’article de la liste locale.
|
|
||||||
- Sur erreur de publication, message d’erreur affiché (aucun fallback silencieux).
|
|
||||||
103
features/features.md
Normal file
103
features/features.md
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
# Fonctionnalités implémentées
|
||||||
|
|
||||||
|
**Auteur** : Équipe 4NK
|
||||||
|
|
||||||
|
## Architecture de base
|
||||||
|
|
||||||
|
### Nostr Paywall → zapwall4Science
|
||||||
|
- Publication d'articles avec aperçus gratuits et contenu payant
|
||||||
|
- Paiement Lightning via Alby/WebLN (remplacement de Rizful)
|
||||||
|
- Connexion via NostrConnect (use.nsec.app)
|
||||||
|
- Interface TypeScript/Next.js
|
||||||
|
|
||||||
|
### Services principaux
|
||||||
|
- **Nostr** : Pool de connexions, publication/récupération d'événements, profils
|
||||||
|
- **Paiements** : Invoices Lightning, vérification zap receipts (NIP-57), envoi automatique contenu privé
|
||||||
|
- **Stockage** : IndexedDB avec chiffrement AES-GCM pour contenu privé
|
||||||
|
- **Notifications** : Surveillance des paiements en temps réel (zap receipts)
|
||||||
|
|
||||||
|
## Fonctionnalités utilisateur
|
||||||
|
|
||||||
|
### Profil et articles
|
||||||
|
- Page profil (`/profile`) avec informations utilisateur
|
||||||
|
- Liste des articles publiés par l'utilisateur
|
||||||
|
- Recherche et filtres (auteur, prix, texte)
|
||||||
|
- Tri (date, prix)
|
||||||
|
|
||||||
|
### Édition et suppression
|
||||||
|
- Édition d'articles via événements Nostr (kind 1 avec tag `replace`)
|
||||||
|
- Suppression d'articles via événements Nostr (kind 5)
|
||||||
|
- Confirmation avant suppression
|
||||||
|
- Ré-encryptage du contenu privé lors de l'édition
|
||||||
|
|
||||||
|
### Notifications
|
||||||
|
- Surveillance automatique des zap receipts (kind:9735) destinés à l'utilisateur
|
||||||
|
- Badge avec nombre de notifications non lues dans le header
|
||||||
|
- Centre de notifications (panneau latéral) avec liste des paiements
|
||||||
|
- Formatage du temps relatif (il y a X minutes/heures/jours)
|
||||||
|
- Marquer comme lu / marquer tout comme lu
|
||||||
|
- Tri par date (plus récentes en premier)
|
||||||
|
|
||||||
|
**Scope** : Uniquement notifications de paiements. Pas de mentions, reposts, likes. Si commentaires demandés plus tard, approbation explicite requise.
|
||||||
|
|
||||||
|
## Stockage
|
||||||
|
|
||||||
|
### IndexedDB avec chiffrement
|
||||||
|
- Remplacement de localStorage par IndexedDB
|
||||||
|
- Chiffrement AES-GCM du contenu privé
|
||||||
|
- Clé maître générée une fois et stockée en localStorage
|
||||||
|
- Secret par article : `<masterKey>:<articleId>`
|
||||||
|
- Expiration automatique (30 jours)
|
||||||
|
- Pas de fallback : échec si IndexedDB ou Web Crypto indisponible
|
||||||
|
|
||||||
|
### Fichiers
|
||||||
|
- `lib/storage/indexedDB.ts` : Service IndexedDB
|
||||||
|
- `lib/storage/cryptoHelpers.ts` : Helpers AES-GCM
|
||||||
|
- `lib/articleStorage.ts` : Gestion du stockage avec chiffrement
|
||||||
|
|
||||||
|
## Séries et médias (NIP-95)
|
||||||
|
|
||||||
|
### Séries
|
||||||
|
- Événements kind 1 avec tag `kind_type: series`
|
||||||
|
- Tags : `site`, `category`, `author`, `series` (self id), `title`, `description`, `cover`, `preview`
|
||||||
|
- Agrégation du sponsoring et des paiements par série
|
||||||
|
|
||||||
|
### Médias
|
||||||
|
- Upload d'images (≤5Mo) et vidéos (≤45Mo) via NIP-95
|
||||||
|
- Tags `banner` et `media` dans les événements
|
||||||
|
- Validations de taille et type
|
||||||
|
- Support dans les articles et séries
|
||||||
|
|
||||||
|
### Avis (reviews)
|
||||||
|
- Événements kind 1 avec tag `kind_type: review`
|
||||||
|
- Tags : `site`, `category`, `author`, `series`, `article`, `reviewer`, `title`
|
||||||
|
- Rémunération possible avec tags `rewarded` et `reward_amount`
|
||||||
|
|
||||||
|
## Optimisations et nettoyage
|
||||||
|
|
||||||
|
### Refactoring
|
||||||
|
- Division des fichiers > 250 lignes
|
||||||
|
- Extraction des fonctions > 40 lignes
|
||||||
|
- Modules dédiés : parsing, messages privés, vérification zap, subscriptions, polling, résolution invoices, stockage, handlers
|
||||||
|
|
||||||
|
### Code quality
|
||||||
|
- Respect strict `exactOptionalPropertyTypes`
|
||||||
|
- Fonctions < 40 lignes, fichiers < 250 lignes
|
||||||
|
- Pas de fallback implicite
|
||||||
|
- Logs structurés
|
||||||
|
- Pas d'analytics
|
||||||
|
|
||||||
|
## Intégrations
|
||||||
|
|
||||||
|
### Alby/WebLN
|
||||||
|
- Remplacement de Rizful par Alby/WebLN
|
||||||
|
- Standard WebLN compatible avec tous les portefeuilles
|
||||||
|
- Pas d'API backend nécessaire
|
||||||
|
- Service `AlbyService` pour enable, makeInvoice, sendPayment
|
||||||
|
|
||||||
|
### Priorité 1 (implémenté)
|
||||||
|
- Génération d'invoice côté auteur lors de la publication
|
||||||
|
- Invoice stockée dans tags Nostr et localStorage
|
||||||
|
- Vérification de l'invoice avant création d'une nouvelle
|
||||||
|
- Signature distante (NIP-46) préparée
|
||||||
|
|
||||||
@ -1,138 +0,0 @@
|
|||||||
# Implémentation du filtrage et de la recherche d'articles
|
|
||||||
|
|
||||||
**Date** : Décembre 2024
|
|
||||||
**Status** : ✅ Complété
|
|
||||||
|
|
||||||
## Objectif
|
|
||||||
|
|
||||||
Permettre aux utilisateurs de rechercher et filtrer les articles sur la page d'accueil.
|
|
||||||
|
|
||||||
## Fonctionnalités implémentées
|
|
||||||
|
|
||||||
### 1. Recherche par texte
|
|
||||||
- Barre de recherche permettant de rechercher dans les titres, aperçus et contenus des articles
|
|
||||||
- Recherche insensible à la casse
|
|
||||||
- Bouton pour effacer la recherche rapidement
|
|
||||||
|
|
||||||
### 2. Filtres
|
|
||||||
- **Filtre par auteur** : Sélectionner un auteur spécifique parmi les auteurs disponibles
|
|
||||||
- **Filtre par prix minimum** : Filtrer les articles avec un prix minimum en satoshis
|
|
||||||
- **Filtre par prix maximum** : Filtrer les articles avec un prix maximum en satoshis
|
|
||||||
|
|
||||||
### 3. Tri
|
|
||||||
- **Plus récent** (par défaut) : Articles les plus récents en premier
|
|
||||||
- **Plus ancien** : Articles les plus anciens en premier
|
|
||||||
- **Prix croissant** : Articles du moins cher au plus cher
|
|
||||||
- **Prix décroissant** : Articles du plus cher au moins cher
|
|
||||||
|
|
||||||
### 4. Affichage des résultats
|
|
||||||
- Compteur affichant le nombre d'articles correspondant aux filtres
|
|
||||||
- Message lorsque aucun article ne correspond aux critères
|
|
||||||
|
|
||||||
## Fichiers créés
|
|
||||||
|
|
||||||
### `components/SearchBar.tsx`
|
|
||||||
Composant de barre de recherche avec :
|
|
||||||
- Icône de recherche
|
|
||||||
- Champ de saisie
|
|
||||||
- Bouton pour effacer la recherche
|
|
||||||
- Gestion de l'état local avec synchronisation
|
|
||||||
|
|
||||||
### `components/ArticleFilters.tsx`
|
|
||||||
Composant de filtres avec :
|
|
||||||
- Filtre par auteur (dropdown)
|
|
||||||
- Filtres par prix min/max (inputs numériques)
|
|
||||||
- Tri (dropdown)
|
|
||||||
- Bouton "Clear all" pour réinitialiser tous les filtres
|
|
||||||
- Affichage conditionnel du bouton "Clear all" seulement si des filtres sont actifs
|
|
||||||
|
|
||||||
**Types exportés** :
|
|
||||||
- `SortOption` : Type pour les options de tri
|
|
||||||
- `ArticleFilters` : Interface pour les filtres
|
|
||||||
|
|
||||||
### `lib/articleFiltering.ts`
|
|
||||||
Logique de filtrage et de tri avec :
|
|
||||||
- `filterArticlesBySearch()` : Filtre par texte de recherche
|
|
||||||
- `filterArticles()` : Filtre par auteur et prix
|
|
||||||
- `sortArticles()` : Trie les articles selon l'option sélectionnée
|
|
||||||
- `applyFiltersAndSort()` : Applique tous les filtres et le tri
|
|
||||||
|
|
||||||
## Fichiers modifiés
|
|
||||||
|
|
||||||
### `hooks/useArticles.ts`
|
|
||||||
- Ajout des paramètres `searchQuery` et `filters` au hook
|
|
||||||
- Utilisation de `useMemo` pour optimiser le filtrage
|
|
||||||
- Retour de `allArticles` (tous les articles non filtrés) pour permettre au composant de filtres de connaître les options disponibles
|
|
||||||
- Retour de `articles` (articles filtrés et triés) pour l'affichage
|
|
||||||
|
|
||||||
**Signature modifiée** :
|
|
||||||
```typescript
|
|
||||||
export function useArticles(
|
|
||||||
searchQuery: string = '',
|
|
||||||
filters: ArticleFilters | null = null
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Retour modifié** :
|
|
||||||
```typescript
|
|
||||||
{
|
|
||||||
articles: Article[], // Articles filtrés et triés
|
|
||||||
allArticles: Article[], // Tous les articles (pour les filtres)
|
|
||||||
loading: boolean,
|
|
||||||
error: string | null,
|
|
||||||
loadArticleContent: (articleId: string, authorPubkey: string) => Promise<Article | null>
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `pages/index.tsx`
|
|
||||||
- Ajout de l'état pour `searchQuery` et `filters`
|
|
||||||
- Intégration du composant `SearchBar`
|
|
||||||
- Intégration du composant `ArticleFilters`
|
|
||||||
- Passage des paramètres au hook `useArticles`
|
|
||||||
- Affichage du compteur d'articles filtrés
|
|
||||||
- Message amélioré lorsque aucun article ne correspond
|
|
||||||
|
|
||||||
## Impact
|
|
||||||
|
|
||||||
### Utilisateur
|
|
||||||
- Recherche rapide d'articles par mots-clés
|
|
||||||
- Filtrage précis par auteur et prix
|
|
||||||
- Tri flexible pour trouver facilement ce qui intéresse
|
|
||||||
- Interface intuitive avec boutons de réinitialisation
|
|
||||||
|
|
||||||
### Technique
|
|
||||||
- Code modulaire et réutilisable
|
|
||||||
- Performance optimisée avec `useMemo`
|
|
||||||
- Types TypeScript stricts pour la sécurité
|
|
||||||
- Séparation claire des responsabilités (UI vs logique)
|
|
||||||
|
|
||||||
## Tests recommandés
|
|
||||||
|
|
||||||
1. **Recherche** :
|
|
||||||
- Rechercher par titre
|
|
||||||
- Rechercher par contenu d'aperçu
|
|
||||||
- Rechercher avec plusieurs mots
|
|
||||||
- Effacer la recherche
|
|
||||||
|
|
||||||
2. **Filtres** :
|
|
||||||
- Filtrer par auteur
|
|
||||||
- Filtrer par prix minimum
|
|
||||||
- Filtrer par prix maximum
|
|
||||||
- Combiner plusieurs filtres
|
|
||||||
- Réinitialiser les filtres
|
|
||||||
|
|
||||||
3. **Tri** :
|
|
||||||
- Trier par date (nouveaux/anciens)
|
|
||||||
- Trier par prix (croissant/décroissant)
|
|
||||||
- Combiner tri et filtres
|
|
||||||
|
|
||||||
4. **Performance** :
|
|
||||||
- Vérifier que le filtrage ne bloque pas l'UI
|
|
||||||
- Vérifier avec un grand nombre d'articles
|
|
||||||
|
|
||||||
## Notes techniques
|
|
||||||
|
|
||||||
- Le filtrage est effectué côté client (pas de requête au serveur/relay)
|
|
||||||
- Les articles sont filtrés et triés à chaque changement de recherche ou filtres
|
|
||||||
- L'utilisation de `useMemo` évite de recalculer les filtres à chaque render
|
|
||||||
- Les filtres sont appliqués dans l'ordre : recherche → filtres → tri
|
|
||||||
@ -1,134 +0,0 @@
|
|||||||
# Résumé final du nettoyage et optimisation
|
|
||||||
|
|
||||||
**Date** : Décembre 2025 (addendum)
|
|
||||||
|
|
||||||
## ✅ Objectifs complétés
|
|
||||||
|
|
||||||
### 1. Nettoyage des fichiers/dossiers obsolètes
|
|
||||||
- ✅ Supprimé `pages/api/rizful/` (dossier vide après migration vers Alby)
|
|
||||||
- ✅ Documentation Rizful conservée pour référence historique
|
|
||||||
|
|
||||||
### 2. Optimisation des fichiers > 250 lignes
|
|
||||||
Tous les fichiers sont maintenant **< 250 lignes** :
|
|
||||||
- `lib/nostr.ts` : 331 → **232 lignes** (-30%)
|
|
||||||
- `lib/articlePublisher.ts` : 237 → **210 lignes** (-11%)
|
|
||||||
- `lib/payment.ts` : 195 → **113 lignes** (-42%)
|
|
||||||
- `lib/nostrconnect.ts` : 156 → **145 lignes** (-7%)
|
|
||||||
|
|
||||||
### 3. Division des fonctions > 40 lignes
|
|
||||||
Toutes les fonctions longues ont été extraites dans des modules dédiés :
|
|
||||||
- Parsing d'événements → `nostrEventParsing.ts`
|
|
||||||
- Messages privés → `nostrPrivateMessages.ts`
|
|
||||||
- Vérification zap → `nostrZapVerification.ts`
|
|
||||||
- Subscriptions → `nostrSubscription.ts`
|
|
||||||
- Polling paiements → `paymentPolling.ts`
|
|
||||||
- Résolution invoices → `invoiceResolver.ts`
|
|
||||||
- Stockage articles → `articleStorage.ts`
|
|
||||||
- Création invoices → `articleInvoice.ts`
|
|
||||||
- Handler NostrConnect → `nostrconnectHandler.ts`
|
|
||||||
|
|
||||||
### 4. Correction des erreurs de lint
|
|
||||||
- ✅ Aucune erreur de lint dans le code TypeScript (déc. 2025 : `npm run lint` OK)
|
|
||||||
- ✅ Code propre et optimisé
|
|
||||||
|
|
||||||
## Addendum Déc 2025
|
|
||||||
- Séries, critiques, agrégations zap : nouvelles sections UI/logic (`Series*`, `ArticleReviews`, `zapAggregation*`).
|
|
||||||
- Upload médias NIP-95 (images/vidéos) avec validations de taille et type.
|
|
||||||
- Stockage contenu privé chiffré en IndexedDB + helpers WebCrypto.
|
|
||||||
- Respect strict `exactOptionalPropertyTypes`, fonctions < 40 lignes, fichiers < 250 lignes (refactors composants profil/articles, sélecteurs de séries).
|
|
||||||
- Pas de tests ajoutés, pas d’analytics.
|
|
||||||
|
|
||||||
## Nouveaux fichiers créés (9 fichiers)
|
|
||||||
|
|
||||||
1. **`lib/nostrEventParsing.ts`** (40 lignes)
|
|
||||||
- Parsing des événements Nostr en articles
|
|
||||||
- Extraction des tags (title, preview, zap, invoice)
|
|
||||||
|
|
||||||
2. **`lib/nostrPrivateMessages.ts`** (59 lignes)
|
|
||||||
- Gestion des messages privés chiffrés
|
|
||||||
- Décryptage avec NIP-04
|
|
||||||
|
|
||||||
3. **`lib/nostrZapVerification.ts`** (61 lignes)
|
|
||||||
- Vérification des zap receipts
|
|
||||||
- Intégration avec zapVerificationService
|
|
||||||
|
|
||||||
4. **`lib/nostrSubscription.ts`** (44 lignes)
|
|
||||||
- Utilitaires pour subscriptions avec timeout
|
|
||||||
- Gestion propre des timeouts et cleanup
|
|
||||||
|
|
||||||
5. **`lib/paymentPolling.ts`** (85 lignes)
|
|
||||||
- Polling pour vérification des paiements
|
|
||||||
- Envoi automatique du contenu privé après paiement
|
|
||||||
|
|
||||||
6. **`lib/invoiceResolver.ts`** (39 lignes)
|
|
||||||
- Résolution intelligente des invoices
|
|
||||||
- Priorité : tags → localStorage → création nouvelle
|
|
||||||
|
|
||||||
7. **`lib/articleStorage.ts`** (93 lignes)
|
|
||||||
- Gestion du stockage localStorage
|
|
||||||
- Fonctions pour stocker/récupérer/supprimer
|
|
||||||
|
|
||||||
8. **`lib/articleInvoice.ts`** (50 lignes)
|
|
||||||
- Création d'invoices Lightning
|
|
||||||
- Création d'événements preview avec tags
|
|
||||||
|
|
||||||
9. **`lib/nostrconnectHandler.ts`** (32 lignes)
|
|
||||||
- Handler pour messages NostrConnect
|
|
||||||
- Validation de sécurité (origin)
|
|
||||||
|
|
||||||
## Statistiques finales
|
|
||||||
|
|
||||||
### Taille des fichiers lib/ (par ordre décroissant)
|
|
||||||
```
|
|
||||||
nostr.ts 232 lignes
|
|
||||||
articlePublisher.ts 210 lignes
|
|
||||||
alby.ts 184 lignes
|
|
||||||
payment.ts 113 lignes ✅ (réduit de 195)
|
|
||||||
nostrconnect.ts 145 lignes
|
|
||||||
zapVerification.ts 97 lignes
|
|
||||||
articleStorage.ts 93 lignes (nouveau)
|
|
||||||
paymentPolling.ts 85 lignes (nouveau)
|
|
||||||
retry.ts 76 lignes
|
|
||||||
nostrZapVerification.ts 61 lignes (nouveau)
|
|
||||||
nostrPrivateMessages.ts 59 lignes (nouveau)
|
|
||||||
nostrRemoteSigner.ts 51 lignes
|
|
||||||
articleInvoice.ts 50 lignes (nouveau)
|
|
||||||
nostrSubscription.ts 44 lignes (nouveau)
|
|
||||||
nostrEventParsing.ts 40 lignes (nouveau)
|
|
||||||
invoiceResolver.ts 39 lignes (nouveau)
|
|
||||||
nostrconnectHandler.ts 32 lignes (nouveau)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Réduction totale
|
|
||||||
- **Avant** : 4 fichiers > 250 lignes
|
|
||||||
- **Après** : 0 fichiers > 250 lignes ✅
|
|
||||||
- **Réduction moyenne** : -25% de lignes dans les fichiers principaux
|
|
||||||
- **Fonctions** : Toutes < 40 lignes ✅
|
|
||||||
|
|
||||||
## Architecture finale
|
|
||||||
|
|
||||||
### Séparation des responsabilités
|
|
||||||
- **Parsing** : `nostrEventParsing.ts`
|
|
||||||
- **Communication** : `nostr.ts`, `nostrSubscription.ts`
|
|
||||||
- **Chiffrement** : `nostrPrivateMessages.ts`
|
|
||||||
- **Vérification** : `nostrZapVerification.ts`, `zapVerification.ts`
|
|
||||||
- **Paiements** : `payment.ts`, `paymentPolling.ts`, `invoiceResolver.ts`
|
|
||||||
- **Articles** : `articlePublisher.ts`, `articleStorage.ts`, `articleInvoice.ts`
|
|
||||||
- **Connectivité** : `nostrconnect.ts`, `nostrconnectHandler.ts`
|
|
||||||
- **Lightning** : `alby.ts`, `retry.ts`
|
|
||||||
- **Signature** : `nostrRemoteSigner.ts`
|
|
||||||
|
|
||||||
### Avantages
|
|
||||||
- ✅ Code modulaire et réutilisable
|
|
||||||
- ✅ Responsabilités bien séparées (SRP)
|
|
||||||
- ✅ Tests unitaires facilités
|
|
||||||
- ✅ Maintenance simplifiée
|
|
||||||
- ✅ Imports clairs et explicites
|
|
||||||
- ✅ Pas de dépendances circulaires
|
|
||||||
|
|
||||||
## Prochaines étapes
|
|
||||||
|
|
||||||
Le code est maintenant propre, optimisé et maintenable. Prêt pour :
|
|
||||||
- Tests unitaires
|
|
||||||
- Documentation utilisateur
|
|
||||||
- Fonctionnalités avancées (priorité 3)
|
|
||||||
@ -1,217 +0,0 @@
|
|||||||
# Nostr Paywall - Site d'articles avec aperçus gratuits et contenu payant
|
|
||||||
|
|
||||||
**Auteur** : Équipe 4NK
|
|
||||||
|
|
||||||
## Objectif
|
|
||||||
|
|
||||||
Implémenter un site d'articles sur Nostr permettant :
|
|
||||||
- L'affichage d'aperçus gratuits (notes publiques)
|
|
||||||
- Le déblocage du contenu complet après un zap Lightning de 800 sats
|
|
||||||
- La connexion via NostrConnect (préconisé use.nsec.app)
|
|
||||||
- Une interface moderne et intuitive en TypeScript/Next.js
|
|
||||||
|
|
||||||
## Impacts
|
|
||||||
|
|
||||||
### Utilisateurs
|
|
||||||
- Accès gratuit aux aperçus d'articles
|
|
||||||
- Possibilité de débloquer le contenu complet via paiement Lightning instantané
|
|
||||||
- Connexion sécurisée via NostrConnect sans partager de clés privées
|
|
||||||
- Expérience utilisateur fluide avec gestion des paiements intégrée
|
|
||||||
|
|
||||||
### Développeurs
|
|
||||||
- Architecture modulaire avec séparation des responsabilités
|
|
||||||
- Utilisation de `nostr-tools` pour toutes les opérations Nostr
|
|
||||||
- TypeScript pour la sécurité de type
|
|
||||||
- Hooks React personnalisés pour la gestion de l'état
|
|
||||||
- Service de connexion NostrConnect réutilisable
|
|
||||||
|
|
||||||
### Technique
|
|
||||||
- Dépendance principale : `nostr-tools` (bibliothèque standard Nostr)
|
|
||||||
- Framework : Next.js 14 avec React 18
|
|
||||||
- Styling : Tailwind CSS
|
|
||||||
- Relay par défaut : wss://relay.damus.io
|
|
||||||
- Bridge NostrConnect : https://use.nsec.app
|
|
||||||
|
|
||||||
## Modifications
|
|
||||||
|
|
||||||
### Structure du projet
|
|
||||||
|
|
||||||
```
|
|
||||||
nostr_paywall/
|
|
||||||
├── pages/
|
|
||||||
│ ├── index.tsx # Page principale avec liste des articles
|
|
||||||
│ └── _app.tsx # Configuration Next.js
|
|
||||||
├── components/
|
|
||||||
│ ├── ConnectButton.tsx # Bouton de connexion NostrConnect
|
|
||||||
│ └── ArticleCard.tsx # Carte d'article avec aperçu et déblocage
|
|
||||||
├── hooks/
|
|
||||||
│ ├── useNostrConnect.ts # Hook pour la connexion NostrConnect
|
|
||||||
│ └── useArticles.ts # Hook pour la gestion des articles
|
|
||||||
├── lib/
|
|
||||||
│ ├── nostr.ts # Service Nostr (publications, abonnements, zaps)
|
|
||||||
│ └── nostrconnect.ts # Service NostrConnect (NIP-46)
|
|
||||||
├── types/
|
|
||||||
│ └── nostr.ts # Types TypeScript pour Nostr
|
|
||||||
└── styles/
|
|
||||||
└── globals.css # Styles globaux avec Tailwind
|
|
||||||
```
|
|
||||||
|
|
||||||
### Composants clés
|
|
||||||
|
|
||||||
#### `lib/nostr.ts` - Service Nostr
|
|
||||||
- `SimplePool` pour la gestion des connexions aux relais
|
|
||||||
- Méthodes pour publier et s'abonner aux événements
|
|
||||||
- Parsing des articles depuis les événements kind:1
|
|
||||||
- Gestion des messages privés chiffrés (kind:4) avec NIP-04
|
|
||||||
- Création de zap requests (kind:9734)
|
|
||||||
- Vérification des zap receipts (kind:9735)
|
|
||||||
|
|
||||||
#### `lib/nostrconnect.ts` - Service NostrConnect
|
|
||||||
- Implémentation du protocole NIP-46 via use.nsec.app
|
|
||||||
- Communication via messages postMessage avec popup
|
|
||||||
- Persistance de l'état de connexion dans localStorage
|
|
||||||
- Gestion du profil utilisateur
|
|
||||||
|
|
||||||
#### `components/ArticleCard.tsx`
|
|
||||||
- Affichage de l'aperçu (contenu public)
|
|
||||||
- Bouton de déblocage conditionnel (nécessite connexion)
|
|
||||||
- Création de zap request lors du clic
|
|
||||||
- Vérification du paiement et chargement du contenu privé
|
|
||||||
- Affichage du contenu complet une fois débloqué
|
|
||||||
|
|
||||||
### Format des articles
|
|
||||||
|
|
||||||
Les articles sont publiés sous forme d'événements Nostr avec :
|
|
||||||
|
|
||||||
**Note publique (kind:1)** - Aperçu :
|
|
||||||
- Tags : `title`, `preview`, `zap` (montant en sats)
|
|
||||||
- Contenu : Aperçu de l'article
|
|
||||||
|
|
||||||
**Message privé (kind:4)** - Contenu complet :
|
|
||||||
- Tag `e` : ID de l'article lié
|
|
||||||
- Contenu : Contenu complet chiffré avec NIP-04
|
|
||||||
- Envoyé après réception du zap
|
|
||||||
|
|
||||||
### Flux de paiement
|
|
||||||
|
|
||||||
1. Utilisateur clique sur "Unlock for 800 sats"
|
|
||||||
2. Création d'un zap request (kind:9734) avec tags `p`, `e`, `amount`
|
|
||||||
3. Le zap request est publié sur le relay
|
|
||||||
4. L'utilisateur complète le paiement via son wallet Lightning
|
|
||||||
5. Vérification du zap receipt (kind:9735) sur le relay
|
|
||||||
6. Déchiffrement et affichage du contenu privé
|
|
||||||
|
|
||||||
## Modalités de déploiement
|
|
||||||
|
|
||||||
### Prérequis
|
|
||||||
- Node.js 18+ et npm
|
|
||||||
- Accès à un relay Nostr public ou privé
|
|
||||||
- Configuration de variables d'environnement optionnelles
|
|
||||||
|
|
||||||
### Variables d'environnement
|
|
||||||
|
|
||||||
Créer un fichier `.env.local` :
|
|
||||||
|
|
||||||
```env
|
|
||||||
NEXT_PUBLIC_NOSTR_RELAY_URL=wss://relay.damus.io
|
|
||||||
NEXT_PUBLIC_NOSTRCONNECT_BRIDGE=https://use.nsec.app
|
|
||||||
```
|
|
||||||
|
|
||||||
### Installation
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
### Développement
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
Le site sera accessible sur http://localhost:3000
|
|
||||||
|
|
||||||
### Build de production
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run build
|
|
||||||
npm start
|
|
||||||
```
|
|
||||||
|
|
||||||
### Déploiement
|
|
||||||
|
|
||||||
Le projet peut être déployé sur :
|
|
||||||
- Vercel (recommandé pour Next.js)
|
|
||||||
- Netlify
|
|
||||||
- Tout hébergeur supportant Node.js
|
|
||||||
|
|
||||||
**Important** : Pour la production, configurer :
|
|
||||||
- Variables d'environnement dans le panneau d'administration
|
|
||||||
- HTTPS (obligatoire pour NostrConnect)
|
|
||||||
- Relay Nostr fiable et performant
|
|
||||||
|
|
||||||
## Modalités d'analyse
|
|
||||||
|
|
||||||
### Logs et debugging
|
|
||||||
|
|
||||||
Les erreurs sont loggées dans la console du navigateur :
|
|
||||||
- Erreurs de connexion aux relais
|
|
||||||
- Erreurs de déchiffrement
|
|
||||||
- Erreurs de parsing d'articles
|
|
||||||
|
|
||||||
### Métriques à surveiller
|
|
||||||
|
|
||||||
1. **Connectivité**
|
|
||||||
- Taux de connexion réussie via NostrConnect
|
|
||||||
- Temps de réponse des relais
|
|
||||||
|
|
||||||
2. **Articles**
|
|
||||||
- Nombre d'articles chargés
|
|
||||||
- Temps de chargement des aperçus
|
|
||||||
- Taux de conversion (aperçu → déblocage)
|
|
||||||
|
|
||||||
3. **Paiements**
|
|
||||||
- Nombre de zap requests créés
|
|
||||||
- Taux de confirmation des zaps
|
|
||||||
- Temps moyen entre zap request et receipt
|
|
||||||
|
|
||||||
4. **Utilisateurs**
|
|
||||||
- Nombre d'utilisateurs connectés
|
|
||||||
- Profils chargés avec succès
|
|
||||||
|
|
||||||
### Points d'amélioration
|
|
||||||
|
|
||||||
1. **Gestion des zaps**
|
|
||||||
- Implémentation complète du flux Lightning avec intégration wallet
|
|
||||||
- Webhooks pour les confirmations de zap
|
|
||||||
- Interface de paiement intégrée (LNURL, Lightning Address)
|
|
||||||
|
|
||||||
2. **Sécurité**
|
|
||||||
- Vérification des signatures des zap receipts
|
|
||||||
- Validation stricte des événements reçus
|
|
||||||
- Gestion des erreurs de déchiffrement
|
|
||||||
|
|
||||||
3. **Performance**
|
|
||||||
- Mise en cache des articles chargés
|
|
||||||
- Pagination pour les grandes listes
|
|
||||||
- Indexation des articles par tags
|
|
||||||
|
|
||||||
4. **UX**
|
|
||||||
- Feedback visuel pendant le traitement des zaps
|
|
||||||
- Gestion des états de chargement
|
|
||||||
- Messages d'erreur plus explicites
|
|
||||||
|
|
||||||
### Tests recommandés
|
|
||||||
|
|
||||||
1. **Tests unitaires**
|
|
||||||
- Parsing d'événements en articles
|
|
||||||
- Déchiffrement de messages privés
|
|
||||||
- Création de zap requests
|
|
||||||
|
|
||||||
2. **Tests d'intégration**
|
|
||||||
- Flux complet de connexion NostrConnect
|
|
||||||
- Flux complet de déblocage d'article
|
|
||||||
- Gestion des erreurs réseau
|
|
||||||
|
|
||||||
3. **Tests end-to-end**
|
|
||||||
- Scénario utilisateur complet (connexion → aperçu → paiement → contenu)
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
# Notifications scope (Dec 2025)
|
|
||||||
|
|
||||||
**Decision:** Do not implement notifications for mentions, reposts, or likes. Only payment notifications remain active. If comment notifications are later requested, they must be explicitly approved.
|
|
||||||
|
|
||||||
**Impacts:**
|
|
||||||
- No parsing/subscription for mention/repost/like events.
|
|
||||||
- UI does not surface badges or panels for these types.
|
|
||||||
- Avoids extra relay traffic and parsing logic.
|
|
||||||
|
|
||||||
**Constraints/quality:**
|
|
||||||
- No fallbacks.
|
|
||||||
- No analytics.
|
|
||||||
- Keep error logging structured if new notification types are ever added.
|
|
||||||
- Respect accessibility and lint/typing rules already in place.
|
|
||||||
@ -1,85 +0,0 @@
|
|||||||
# Implémentation Priorité 1
|
|
||||||
|
|
||||||
**Auteur** : Équipe 4NK
|
|
||||||
|
|
||||||
## Objectif
|
|
||||||
|
|
||||||
Implémenter les fonctionnalités critiques de priorité 1 :
|
|
||||||
1. Signature distante pour publication d'articles (NIP-46)
|
|
||||||
2. Génération d'invoice côté auteur lors de la publication
|
|
||||||
|
|
||||||
## Modifications
|
|
||||||
|
|
||||||
### 1. Génération d'invoice côté auteur
|
|
||||||
|
|
||||||
**Fichiers modifiés** :
|
|
||||||
- `lib/articlePublisher.ts` : Ajout de la création d'invoice lors de la publication
|
|
||||||
- `lib/payment.ts` : Vérification de l'invoice de l'auteur avant d'en créer une nouvelle
|
|
||||||
|
|
||||||
**Fonctionnement** :
|
|
||||||
- Lors de la publication, l'auteur crée une facture Lightning via Alby/WebLN
|
|
||||||
- L'invoice est stockée dans les tags de l'événement Nostr (`invoice`, `payment_hash`)
|
|
||||||
- L'invoice est également stockée dans localStorage (pour récupération rapide)
|
|
||||||
- Lors du paiement, le système vérifie d'abord si une invoice existe et n'est pas expirée
|
|
||||||
- Si aucune invoice valide, le lecteur peut en créer une nouvelle
|
|
||||||
|
|
||||||
**Avantages** :
|
|
||||||
- Meilleure traçabilité (invoice créée par l'auteur)
|
|
||||||
- L'invoice peut être réutilisée par plusieurs lecteurs
|
|
||||||
- L'invoice est visible dans l'événement Nostr (tags)
|
|
||||||
|
|
||||||
### 2. Signature distante améliorée
|
|
||||||
|
|
||||||
**Fichiers modifiés** :
|
|
||||||
- `lib/nostrRemoteSigner.ts` : Amélioration du support de signature
|
|
||||||
- `lib/articlePublisher.ts` : Support optionnel de la clé privée
|
|
||||||
- `components/ArticleEditor.tsx` : Utilisation améliorée
|
|
||||||
|
|
||||||
**Fonctionnement** :
|
|
||||||
- Si la clé privée est disponible (via NostrConnect), utilisation de la signature directe
|
|
||||||
- Si pas de clé privée, message d'erreur explicite
|
|
||||||
- Préparation pour future implémentation NIP-46 complète
|
|
||||||
|
|
||||||
**Note** : L'implémentation complète de NIP-46 nécessiterait une connexion WebSocket permanente avec un relay, ce qui est complexe. Pour l'instant, le système fonctionne avec les clés privées fournies par NostrConnect via postMessage.
|
|
||||||
|
|
||||||
## Détails techniques
|
|
||||||
|
|
||||||
### Invoice dans les tags Nostr
|
|
||||||
|
|
||||||
Les invoices créées par l'auteur sont stockées dans les tags de l'événement :
|
|
||||||
```
|
|
||||||
tags: [
|
|
||||||
['invoice', 'lnbc...'], // Invoice BOLT11
|
|
||||||
['payment_hash', 'abc123...'], // Payment hash
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Stockage local
|
|
||||||
|
|
||||||
Les invoices sont également stockées dans localStorage avec le contenu privé :
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"content": "...",
|
|
||||||
"authorPubkey": "...",
|
|
||||||
"articleId": "...",
|
|
||||||
"invoice": {
|
|
||||||
"invoice": "lnbc...",
|
|
||||||
"paymentHash": "...",
|
|
||||||
"amount": 800,
|
|
||||||
"expiresAt": 1234567890
|
|
||||||
},
|
|
||||||
"createdAt": 1234567890
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Limitations actuelles
|
|
||||||
|
|
||||||
1. **Signature distante** : NIP-46 complet non implémenté (nécessite WebSocket relay)
|
|
||||||
2. **Stockage invoice** : localStorage côté client (pas accessible entre lecteurs)
|
|
||||||
3. **Récupération invoice** : Actuellement via localStorage, idéalement depuis les tags de l'événement
|
|
||||||
|
|
||||||
## Améliorations futures
|
|
||||||
|
|
||||||
1. Parser l'invoice directement depuis les tags de l'événement Nostr
|
|
||||||
2. Implémenter NIP-46 complet pour la signature distante
|
|
||||||
3. Utiliser une base de données pour le stockage au lieu de localStorage
|
|
||||||
@ -1,215 +0,0 @@
|
|||||||
# Intégration Rizful.com API pour paiements Lightning et identités
|
|
||||||
|
|
||||||
**Auteur** : Équipe 4NK
|
|
||||||
|
|
||||||
## Objectif
|
|
||||||
|
|
||||||
Intégrer l'API de Rizful.com pour :
|
|
||||||
- Générer des identités Nostr
|
|
||||||
- Créer et gérer des factures Lightning pour les paiements d'articles
|
|
||||||
- Vérifier le statut des paiements Lightning
|
|
||||||
- Fournir une expérience de paiement fluide via Rizful
|
|
||||||
|
|
||||||
## Impacts
|
|
||||||
|
|
||||||
### Utilisateurs
|
|
||||||
- Paiements Lightning facilités via l'infrastructure Rizful
|
|
||||||
- Interface de paiement améliorée avec modal dédiée
|
|
||||||
- Vérification automatique des paiements
|
|
||||||
- Possibilité de générer des identités Nostr via Rizful
|
|
||||||
|
|
||||||
### Développeurs
|
|
||||||
- Service Rizful centralisé pour toutes les opérations de paiement
|
|
||||||
- Intégration transparente avec le système de paiement existant
|
|
||||||
- Gestion des factures Lightning standardisée
|
|
||||||
- API unifiée pour les identités et paiements
|
|
||||||
|
|
||||||
### Technique
|
|
||||||
- Nouveau service `RizfulService` pour les appels API
|
|
||||||
- Service `PaymentService` intégrant Rizful avec Nostr
|
|
||||||
- Composant `PaymentModal` pour l'affichage des factures
|
|
||||||
- Variables d'environnement pour la configuration API
|
|
||||||
|
|
||||||
## Modifications
|
|
||||||
|
|
||||||
### Nouveaux fichiers
|
|
||||||
|
|
||||||
#### `lib/rizful.ts` - Service Rizful API
|
|
||||||
Service principal pour interagir avec l'API Rizful.com :
|
|
||||||
- `createInvoice()` : Créer une facture Lightning
|
|
||||||
- `checkPaymentStatus()` : Vérifier le statut d'un paiement
|
|
||||||
- `waitForPayment()` : Polling jusqu'à confirmation du paiement
|
|
||||||
- `generateIdentity()` : Générer une nouvelle identité Nostr
|
|
||||||
- `getLightningAddress()` : Obtenir l'adresse Lightning d'une identité
|
|
||||||
- `createPaymentLink()` : Créer un lien de paiement avec URL Lightning
|
|
||||||
|
|
||||||
#### `lib/payment.ts` - Service de paiement intégré
|
|
||||||
Service intégrant Rizful avec le système Nostr :
|
|
||||||
- `createArticlePayment()` : Créer une facture pour un article
|
|
||||||
- `checkArticlePayment()` : Vérifier le paiement d'un article
|
|
||||||
- `waitForArticlePayment()` : Attendre la confirmation du paiement
|
|
||||||
- `getPaymentUrl()` : Obtenir l'URL de paiement pour un article
|
|
||||||
|
|
||||||
#### `types/rizful.ts` - Types TypeScript
|
|
||||||
Types pour l'API Rizful :
|
|
||||||
- `RizfulConfig` : Configuration du service
|
|
||||||
- `RizfulInvoice` : Structure d'une facture Lightning
|
|
||||||
- `RizfulPaymentStatus` : Statut d'un paiement
|
|
||||||
- `RizfulIdentity` : Identité Nostr générée
|
|
||||||
- `RizfulInvoiceRequest` : Requête de création de facture
|
|
||||||
|
|
||||||
#### `components/PaymentModal.tsx` - Modal de paiement
|
|
||||||
Composant React pour afficher la facture Lightning :
|
|
||||||
- Affichage de la facture en texte
|
|
||||||
- Bouton pour copier la facture
|
|
||||||
- Bouton pour ouvrir le wallet Lightning
|
|
||||||
- Interface utilisateur claire et intuitive
|
|
||||||
|
|
||||||
### Modifications des fichiers existants
|
|
||||||
|
|
||||||
#### `components/ArticleCard.tsx`
|
|
||||||
- Intégration du `PaymentService` au lieu du système de zap direct
|
|
||||||
- Affichage de `PaymentModal` lors de la création d'une facture
|
|
||||||
- Polling automatique pour vérifier le paiement en arrière-plan
|
|
||||||
- Gestion améliorée des états de paiement
|
|
||||||
|
|
||||||
#### `next.config.js`
|
|
||||||
- Ajout des variables d'environnement Rizful :
|
|
||||||
- `RIZFUL_API_KEY` : Clé API Rizful
|
|
||||||
- `RIZFUL_API_URL` : URL de l'API Rizful (défaut: https://api.rizful.com)
|
|
||||||
|
|
||||||
### Flux de paiement avec Rizful
|
|
||||||
|
|
||||||
1. **Utilisateur clique sur "Unlock for X sats"**
|
|
||||||
- Vérification de la connexion Nostr
|
|
||||||
- Création d'une facture Lightning via Rizful API
|
|
||||||
|
|
||||||
2. **Affichage de la modal de paiement**
|
|
||||||
- Facture Lightning affichée
|
|
||||||
- Options pour copier ou ouvrir dans wallet
|
|
||||||
|
|
||||||
3. **Paiement utilisateur**
|
|
||||||
- Utilisateur paie via son wallet Lightning
|
|
||||||
- Paiement traité par Rizful
|
|
||||||
|
|
||||||
4. **Vérification du paiement**
|
|
||||||
- Polling automatique du statut via Rizful API
|
|
||||||
- Vérification supplémentaire via zap receipt sur Nostr (double confirmation)
|
|
||||||
|
|
||||||
5. **Déblocage du contenu**
|
|
||||||
- Une fois le paiement confirmé, chargement du contenu privé
|
|
||||||
- Affichage du contenu complet
|
|
||||||
|
|
||||||
## Modalités de déploiement
|
|
||||||
|
|
||||||
### Prérequis
|
|
||||||
- Compte Rizful.com avec clé API
|
|
||||||
- Variables d'environnement configurées
|
|
||||||
|
|
||||||
### Configuration
|
|
||||||
|
|
||||||
Créer ou mettre à jour le fichier `.env.local` :
|
|
||||||
|
|
||||||
```env
|
|
||||||
# Rizful API Configuration
|
|
||||||
NEXT_PUBLIC_RIZFUL_API_KEY=your_rizful_api_key_here
|
|
||||||
NEXT_PUBLIC_RIZFUL_API_URL=https://api.rizful.com
|
|
||||||
|
|
||||||
# Existing Nostr configuration
|
|
||||||
NEXT_PUBLIC_NOSTR_RELAY_URL=wss://relay.damus.io
|
|
||||||
NEXT_PUBLIC_NOSTRCONNECT_BRIDGE=https://use.nsec.app
|
|
||||||
```
|
|
||||||
|
|
||||||
### Obtenir une clé API Rizful
|
|
||||||
|
|
||||||
1. Créer un compte sur [Rizful.com](https://rizful.com/)
|
|
||||||
2. Accéder aux paramètres du compte
|
|
||||||
3. Générer une clé API
|
|
||||||
4. Configurer l'adresse Lightning personnalisée (optionnel)
|
|
||||||
5. Copier la clé API dans les variables d'environnement
|
|
||||||
|
|
||||||
### Déploiement
|
|
||||||
|
|
||||||
Aucun changement dans le processus de déploiement standard :
|
|
||||||
- Les variables d'environnement doivent être configurées dans l'environnement de production
|
|
||||||
- Le code client peut accéder aux variables `NEXT_PUBLIC_*`
|
|
||||||
- Les appels API se font depuis le navigateur (CORS doit être configuré côté Rizful)
|
|
||||||
|
|
||||||
### Sécurité
|
|
||||||
|
|
||||||
- **Clé API** : Stockée côté client (NEXT_PUBLIC_*), donc accessible dans le navigateur
|
|
||||||
- Rizful devrait implémenter des restrictions par domaine/origine
|
|
||||||
- Considérer un proxy backend pour protéger la clé API en production
|
|
||||||
- **Factures Lightning** : Valides uniquement pendant la période d'expiration
|
|
||||||
- **Vérification double** : Combinaison Rizful API + zap receipts Nostr pour validation
|
|
||||||
|
|
||||||
## Modalités d'analyse
|
|
||||||
|
|
||||||
### Logs et debugging
|
|
||||||
|
|
||||||
Les erreurs sont loggées dans la console du navigateur :
|
|
||||||
- Erreurs de création de facture
|
|
||||||
- Erreurs de vérification de paiement
|
|
||||||
- Timeouts de polling
|
|
||||||
|
|
||||||
### Métriques à surveiller
|
|
||||||
|
|
||||||
1. **API Rizful**
|
|
||||||
- Taux de succès des créations de factures
|
|
||||||
- Temps de réponse de l'API
|
|
||||||
- Taux de confirmation des paiements
|
|
||||||
- Erreurs API (rate limiting, authentification, etc.)
|
|
||||||
|
|
||||||
2. **Paiements**
|
|
||||||
- Temps moyen entre création de facture et paiement
|
|
||||||
- Taux d'abandon de paiement
|
|
||||||
- Taux de confirmation de paiement
|
|
||||||
- Échecs de vérification de paiement
|
|
||||||
|
|
||||||
3. **Expérience utilisateur**
|
|
||||||
- Utilisation de la modal vs ouverture directe du wallet
|
|
||||||
- Taux de copie de facture
|
|
||||||
- Temps d'attente pour confirmation
|
|
||||||
|
|
||||||
### Points d'amélioration
|
|
||||||
|
|
||||||
1. **Backend proxy (recommandé pour production)**
|
|
||||||
- Créer un endpoint Next.js API route pour protéger la clé API
|
|
||||||
- Appels API depuis le serveur au lieu du client
|
|
||||||
- Validation supplémentaire côté serveur
|
|
||||||
|
|
||||||
2. **Gestion des erreurs**
|
|
||||||
- Retry logic pour les appels API échoués
|
|
||||||
- Gestion des timeouts réseau
|
|
||||||
- Messages d'erreur utilisateur plus explicites
|
|
||||||
|
|
||||||
3. **QR Code**
|
|
||||||
- Génération de QR code pour les factures Lightning
|
|
||||||
- Affichage dans la modal de paiement
|
|
||||||
- Compatible avec wallets mobiles
|
|
||||||
|
|
||||||
4. **Webhooks**
|
|
||||||
- Intégration webhooks Rizful pour notifications en temps réel
|
|
||||||
- Éviter le polling continu
|
|
||||||
- Réactivité améliorée
|
|
||||||
|
|
||||||
5. **Identités**
|
|
||||||
- Utilisation de `generateIdentity()` pour créer des identités
|
|
||||||
- Stockage sécurisé des clés privées générées
|
|
||||||
- Intégration avec le système d'authentification
|
|
||||||
|
|
||||||
### Tests recommandés
|
|
||||||
|
|
||||||
1. **Tests unitaires**
|
|
||||||
- `RizfulService.createInvoice()`
|
|
||||||
- `RizfulService.checkPaymentStatus()`
|
|
||||||
- `PaymentService.createArticlePayment()`
|
|
||||||
|
|
||||||
2. **Tests d'intégration**
|
|
||||||
- Flux complet de paiement (création → paiement → vérification)
|
|
||||||
- Gestion des timeouts
|
|
||||||
- Gestion des erreurs API
|
|
||||||
|
|
||||||
3. **Tests end-to-end**
|
|
||||||
- Scénario utilisateur complet avec paiement réel
|
|
||||||
- Vérification du déblocage de contenu après paiement
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
# Storage encryption (IndexedDB) – Dec 2025
|
|
||||||
|
|
||||||
**Scope**
|
|
||||||
- Encrypt private article content and invoices stored in IndexedDB using Web Crypto (AES-GCM).
|
|
||||||
- Deterministic per-article secret derived from a persisted master key.
|
|
||||||
- No fallbacks; fails if IndexedDB or Web Crypto is unavailable.
|
|
||||||
|
|
||||||
**Key management**
|
|
||||||
- Master key generated once in browser (`article_storage_master_key`, random 32 bytes, base64) and kept in localStorage.
|
|
||||||
- Per-article secret: `<masterKey>:<articleId>` (used only client-side).
|
|
||||||
|
|
||||||
**Implementation**
|
|
||||||
- `lib/storage/cryptoHelpers.ts`: AES-GCM helpers (base64 encode/decode, encrypt/decrypt).
|
|
||||||
- `lib/storage/indexedDB.ts`: store/get now require a secret; payloads encrypted; unchanged API surface via `storageService`.
|
|
||||||
- `lib/articleStorage.ts`: derives per-article secret, encrypts content+invoice on write, decrypts on read, same expiration (30 days).
|
|
||||||
|
|
||||||
**Behavior**
|
|
||||||
- If IndexedDB or crypto is unavailable, operations throw (no silent fallback).
|
|
||||||
- Existing data written before encryption won’t decrypt; new writes are encrypted.
|
|
||||||
|
|
||||||
**Next steps (optional)**
|
|
||||||
- Rotate master key with migration plan.
|
|
||||||
- Add per-user secrets or hardware-bound keys if required.
|
|
||||||
@ -1,158 +0,0 @@
|
|||||||
# Implémentation de l'amélioration du stockage du contenu privé
|
|
||||||
|
|
||||||
**Date** : Décembre 2024
|
|
||||||
**Status** : ✅ Complété
|
|
||||||
|
|
||||||
## Objectif
|
|
||||||
|
|
||||||
Remplacer localStorage par IndexedDB pour le stockage du contenu privé des articles, offrant une meilleure fiabilité, une plus grande capacité de stockage et la gestion de l'expiration des données.
|
|
||||||
|
|
||||||
## Fonctionnalités implémentées
|
|
||||||
|
|
||||||
### 1. Service IndexedDB
|
|
||||||
- Service IndexedDB complet avec gestion d'initialisation
|
|
||||||
- Support des index pour les recherches (createdAt, expiresAt)
|
|
||||||
- Gestion des erreurs
|
|
||||||
- Utilisation exclusive d'IndexedDB (pas de fallback)
|
|
||||||
|
|
||||||
### 3. Gestion de l'expiration
|
|
||||||
- Expiration automatique des données (30 jours par défaut)
|
|
||||||
- Suppression automatique des données expirées lors de la récupération
|
|
||||||
- Méthode pour nettoyer toutes les données expirées
|
|
||||||
|
|
||||||
### 4. Migration des fonctions
|
|
||||||
- Toutes les fonctions de stockage sont maintenant async
|
|
||||||
- Compatibilité avec l'API existante (même signature, mais async)
|
|
||||||
- Migration transparente pour le code existant
|
|
||||||
|
|
||||||
## Fichiers créés
|
|
||||||
|
|
||||||
### `lib/storage/indexedDB.ts`
|
|
||||||
Service IndexedDB complet :
|
|
||||||
- `IndexedDBStorage` : Classe pour gérer IndexedDB
|
|
||||||
- `storageService` : Instance exportée de IndexedDBStorage
|
|
||||||
- Méthodes : `set()`, `get()`, `delete()`, `clearExpired()`
|
|
||||||
- Gestion de l'expiration automatique
|
|
||||||
- Utilisation exclusive d'IndexedDB (pas de fallback)
|
|
||||||
|
|
||||||
**Caractéristiques** :
|
|
||||||
- Base de données : `nostr_paywall`
|
|
||||||
- Version : 1
|
|
||||||
- Object store : `article_content`
|
|
||||||
- Index : `createdAt`, `expiresAt`
|
|
||||||
|
|
||||||
### `features/storage-improvement-implementation.md`
|
|
||||||
Documentation de l'implémentation.
|
|
||||||
|
|
||||||
## Fichiers modifiés
|
|
||||||
|
|
||||||
### `lib/articleStorage.ts`
|
|
||||||
- `storePrivateContent()` : Maintenant async, utilise `storageService`
|
|
||||||
- `getStoredPrivateContent()` : Maintenant async, utilise `storageService`
|
|
||||||
- `getStoredInvoice()` : Maintenant async
|
|
||||||
- `removeStoredPrivateContent()` : Maintenant async
|
|
||||||
- Expiration par défaut : 30 jours
|
|
||||||
|
|
||||||
**Changements** :
|
|
||||||
- Remplacement de `localStorage` par `storageService`
|
|
||||||
- Ajout de l'expiration automatique (30 jours)
|
|
||||||
- Toutes les fonctions deviennent async
|
|
||||||
|
|
||||||
### `lib/articlePublisher.ts`
|
|
||||||
- Mise à jour pour utiliser les nouvelles fonctions async
|
|
||||||
- Suppression des méthodes privées dupliquées
|
|
||||||
- Utilisation directe des fonctions exportées de `articleStorage`
|
|
||||||
|
|
||||||
### `lib/invoiceResolver.ts`
|
|
||||||
- `getStoredInvoice()` : Maintenant async avec `await`
|
|
||||||
|
|
||||||
### `lib/paymentPolling.ts`
|
|
||||||
- `getStoredPrivateContent()` : Maintenant async avec `await`
|
|
||||||
|
|
||||||
## Avantages d'IndexedDB vs localStorage
|
|
||||||
|
|
||||||
### IndexedDB
|
|
||||||
- **Capacité** : Plusieurs Go vs ~5-10 MB pour localStorage
|
|
||||||
- **Performance** : Meilleure pour les grandes quantités de données
|
|
||||||
- **Structured** : Base de données structurée avec index
|
|
||||||
- **Transactions** : Support des transactions
|
|
||||||
- **Types** : Support des types complexes (Blob, ArrayBuffer, etc.)
|
|
||||||
|
|
||||||
### localStorage
|
|
||||||
- **Simplicité** : API plus simple (clé-valeur)
|
|
||||||
- **Compatibilité** : Meilleure compatibilité navigateur (mais IndexedDB est maintenant bien supporté)
|
|
||||||
- **Synchronisation** : API synchrone (plus simple mais peut bloquer)
|
|
||||||
|
|
||||||
## Gestion de l'expiration
|
|
||||||
|
|
||||||
### Expiration par défaut
|
|
||||||
- **Durée** : 30 jours (configurable via `DEFAULT_EXPIRATION`)
|
|
||||||
- **Vérification** : Automatique lors de la récupération
|
|
||||||
- **Nettoyage** : Les données expirées sont supprimées automatiquement
|
|
||||||
|
|
||||||
### Expiration personnalisée
|
|
||||||
Les données peuvent être stockées avec une expiration personnalisée :
|
|
||||||
```typescript
|
|
||||||
await storageService.set(key, data, customExpirationInMs)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Exigence IndexedDB
|
|
||||||
|
|
||||||
L'application nécessite IndexedDB pour fonctionner :
|
|
||||||
- Si IndexedDB n'est pas disponible, une erreur sera levée
|
|
||||||
- IndexedDB est supporté par tous les navigateurs modernes
|
|
||||||
- Pas de fallback vers localStorage
|
|
||||||
|
|
||||||
## Migration des données existantes
|
|
||||||
|
|
||||||
Les données existantes dans localStorage restent accessibles :
|
|
||||||
- Les nouvelles données sont stockées dans IndexedDB (ou localStorage en fallback)
|
|
||||||
- Les anciennes données dans localStorage peuvent être lues (si nécessaire)
|
|
||||||
- Pas de migration automatique nécessaire (les données anciennes seront progressivement remplacées)
|
|
||||||
|
|
||||||
## Impact
|
|
||||||
|
|
||||||
### Utilisateur
|
|
||||||
- Stockage plus fiable et performant
|
|
||||||
- Pas de changement visible dans l'interface
|
|
||||||
|
|
||||||
### Technique
|
|
||||||
- Meilleure gestion du stockage
|
|
||||||
- Expiration automatique des données
|
|
||||||
- Support de plus grandes quantités de données
|
|
||||||
- Code plus robuste avec fallback
|
|
||||||
|
|
||||||
## Limitations et améliorations futures
|
|
||||||
|
|
||||||
### Limitations actuelles
|
|
||||||
- Expiration fixe à 30 jours (pas de configuration utilisateur)
|
|
||||||
- Pas de nettoyage périodique automatique (seulement lors de la récupération)
|
|
||||||
- Nécessite IndexedDB (pas de fallback)
|
|
||||||
|
|
||||||
### Améliorations possibles
|
|
||||||
- **Migration automatique** : Migrer les données localStorage vers IndexedDB au premier chargement
|
|
||||||
- **Nettoyage périodique** : Tâche de nettoyage périodique pour supprimer les données expirées
|
|
||||||
- **Configuration** : Permettre à l'utilisateur de configurer l'expiration
|
|
||||||
- **Compression** : Compresser les données avant stockage pour économiser l'espace
|
|
||||||
- **Chiffrement** : Chiffrer les données sensibles avant stockage
|
|
||||||
|
|
||||||
## Tests recommandés
|
|
||||||
|
|
||||||
1. **Stockage** :
|
|
||||||
- Stocker du contenu privé
|
|
||||||
- Vérifier qu'il est stocké correctement
|
|
||||||
- Vérifier qu'il peut être récupéré
|
|
||||||
|
|
||||||
2. **Expiration** :
|
|
||||||
- Stocker avec expiration courte
|
|
||||||
- Attendre l'expiration
|
|
||||||
- Vérifier que les données sont supprimées
|
|
||||||
|
|
||||||
3. **IndexedDB requis** :
|
|
||||||
- Vérifier que l'application fonctionne avec IndexedDB
|
|
||||||
- Vérifier que les erreurs sont gérées correctement si IndexedDB n'est pas disponible
|
|
||||||
|
|
||||||
4. **Performance** :
|
|
||||||
- Tester avec un grand nombre d'articles
|
|
||||||
- Vérifier que les performances sont bonnes
|
|
||||||
- Vérifier qu'il n'y a pas de blocage de l'UI
|
|
||||||
@ -1,71 +0,0 @@
|
|||||||
# Documentation technique – zapwall4science (Dec 2025)
|
|
||||||
|
|
||||||
## 1) Cartographie services/hooks/types (responsabilités, dépendances)
|
|
||||||
|
|
||||||
- **Services Nostr**
|
|
||||||
- `lib/nostr.ts` : pool SimplePool, publish générique, clés locales; queries article.
|
|
||||||
- `lib/nostrEventParsing.ts` : parsing events → Article/Series/Review (tags kind_type, series, media, banner).
|
|
||||||
- `lib/nostrTags.ts` : construction des tags article/série/avis (site, type science-fiction/research, kind_type, media/bannière).
|
|
||||||
- `lib/seriesQueries.ts`, `lib/articleQueries.ts`, `lib/reviews.ts` : fetch séries, articles par série, critiques.
|
|
||||||
- `lib/articlePublisher.ts`, `lib/articleMutations.ts` : publication article/preview/presentation, update/delete, kind_type, séries, médias, bannière.
|
|
||||||
- `lib/seriesAggregation.ts`, `lib/reviewAggregation.ts`, `lib/zapAggregation.ts` : agrégats sponsoring/achats/remerciements.
|
|
||||||
- `lib/zapVerification.ts` : vérification zap receipts (verifyEvent).
|
|
||||||
- `lib/nostrconnect.ts` : Nostr Connect (handler, sécurité).
|
|
||||||
- `lib/nostrRemoteSigner.ts` : signature distante (pas de fallback silencieux).
|
|
||||||
- `lib/nip95.ts` : upload médias NIP-95 (images ≤5Mo, vidéos ≤45Mo, types restreints).
|
|
||||||
- **Paiement / Lightning**
|
|
||||||
- `lib/alby.ts` : WebLN (enable, makeInvoice, sendPayment).
|
|
||||||
- `lib/payment.ts`, `lib/paymentPolling.ts` : statut paiements, polling.
|
|
||||||
- `lib/articleInvoice.ts` : facture article (zapAmount, expiry), tags preview.
|
|
||||||
- **Stockage**
|
|
||||||
- `lib/storage/cryptoHelpers.ts` : AES-GCM, dérivation/import clé, conversions b64.
|
|
||||||
- `lib/storage/indexedDB.ts` : set/get/delete/clearExpired chiffré, TTL.
|
|
||||||
- `lib/articleStorage.ts` : clé maître locale (base64), secret par article, persistance contenu privé + facture.
|
|
||||||
- **Hooks**
|
|
||||||
- `hooks/useArticles.ts`, `hooks/useUserArticles.ts` : subscriptions articles, filtres catégorie, unsubscribe direct (pas de .then).
|
|
||||||
- `hooks/useArticleEditing.ts` : édition/suppression article.
|
|
||||||
- Autres : `useNotificationCenter`, `useNostrConnect`, etc.
|
|
||||||
- **Types**
|
|
||||||
- `types/nostr.ts` : Article, Series, Review, MediaRef, KindType, catégories; exactOptionalPropertyTypes respecté.
|
|
||||||
- `types/nostr-tools-extended.ts` : extensions SimplePool/Sub.
|
|
||||||
- `types/alby.ts` : WebLNProvider, invoice types.
|
|
||||||
|
|
||||||
## 2) Guide Nostr (publication, update/delete, zap, remote signer)
|
|
||||||
|
|
||||||
- Publication générique : `nostrService.publishEvent(eventTemplate)` (signEvent, created_at contrôlé).
|
|
||||||
- Article : `articlePublisher.publishArticle` (preview + tags kind_type/site/category/series/banner/media), contenu privé chiffré stocké.
|
|
||||||
- Update article : `publishArticleUpdate` (`lib/articleMutations.ts`) tags `e` (original) + `replace`, publie preview + contenu privé chiffré.
|
|
||||||
- Delete article : `deleteArticleEvent` (kind 5, tag e) — erreurs remontées, pas de fallback.
|
|
||||||
- Série : `publishSeries` (kind 1, tags kind_type=series, cover, description).
|
|
||||||
- Avis : `publishReview` (kind 1, kind_type=review, article/series/author tags).
|
|
||||||
- Zap verification : `lib/zapVerification.ts` (verifyEvent).
|
|
||||||
- Agrégats : `aggregateZapSats` / `getSeriesAggregates` / `getReviewTipsForArticle`.
|
|
||||||
- Remote signer : `lib/nostrRemoteSigner.ts` (clé fournie), sans valeurs de repli implicites.
|
|
||||||
|
|
||||||
## 3) Guide Stockage
|
|
||||||
|
|
||||||
- Chiffrement : `cryptoHelpers` (AES-GCM), entrée BufferSource conforme Web Crypto.
|
|
||||||
- IndexedDB : `storage/indexedDB.ts` stocke `{ iv, ciphertext, expiresAt }`, purge `clearExpired`.
|
|
||||||
- Secret : `articleStorage` génère clé maître (localStorage, base64, 32 bytes) puis secret `<master>:<articleId>`.
|
|
||||||
- Données : contenu privé + facture, TTL 30 jours, suppression via `removeStoredPrivateContent`.
|
|
||||||
|
|
||||||
## 4) Guide Paiements
|
|
||||||
|
|
||||||
- WebLN/Alby : `lib/alby.ts` (enable, makeInvoice, sendPayment).
|
|
||||||
- Facture article : `createArticleInvoice` (zapAmount, expiry).
|
|
||||||
- Publication article : `articlePublisher` gère preview event + stockage contenu privé.
|
|
||||||
- Polling / vérif : `paymentPolling.ts`, `payment.ts`; agrégats via zap receipts (`zapAggregation.ts`).
|
|
||||||
- Envoi contenu privé : via publisher/mutations après paiement confirmé.
|
|
||||||
|
|
||||||
## 5) Médias / NIP-95
|
|
||||||
|
|
||||||
- Upload via `uploadMedia(file)` (URL `NEXT_PUBLIC_NIP95_UPLOAD_URL`), validation type/taille.
|
|
||||||
- Utilisation dans `MarkdownEditor` (insertion markdown), bannière dans ArticleDraft.
|
|
||||||
|
|
||||||
## 6) Contrib (référence rapide)
|
|
||||||
|
|
||||||
- Lint/typage obligatoires (`npm run lint`, `npm run type-check`).
|
|
||||||
- Pas de tests/analytics ajoutés.
|
|
||||||
- Pas de fallback implicite, pas de `ts-ignore`/`any` non justifié.
|
|
||||||
- Accessibilité : ARIA/clavier/contraste.
|
|
||||||
- Documentation : corrections dans `fixKnowledge/`, features dans `features/`.
|
|
||||||
@ -1,169 +0,0 @@
|
|||||||
# Implémentation du profil utilisateur et des articles de l'utilisateur
|
|
||||||
|
|
||||||
**Date** : Décembre 2024
|
|
||||||
**Status** : ✅ Complété
|
|
||||||
|
|
||||||
## Objectif
|
|
||||||
|
|
||||||
Permettre aux utilisateurs de visualiser leur profil et la liste de leurs articles publiés.
|
|
||||||
|
|
||||||
## Fonctionnalités implémentées
|
|
||||||
|
|
||||||
### 1. Page de profil
|
|
||||||
- Page `/profile` accessible uniquement aux utilisateurs connectés
|
|
||||||
- Affichage des informations du profil (nom, photo, description, pubkey, nip05)
|
|
||||||
- Redirection automatique vers la page d'accueil si non connecté
|
|
||||||
- Compteur d'articles publiés
|
|
||||||
|
|
||||||
### 2. Liste des articles de l'utilisateur
|
|
||||||
- Affichage de tous les articles publiés par l'utilisateur connecté
|
|
||||||
- Recherche et filtres (comme sur la page d'accueil)
|
|
||||||
- Tri des articles (nouveaux/anciens, prix)
|
|
||||||
- Compteur d'articles affichés vs total
|
|
||||||
|
|
||||||
### 3. Lien vers le profil
|
|
||||||
- Le nom/avatar dans `ConnectButton` est maintenant cliquable
|
|
||||||
- Lien vers `/profile` pour accéder rapidement au profil
|
|
||||||
|
|
||||||
### 4. Gestion du profil minimal
|
|
||||||
- Si aucun profil Nostr n'existe, affichage d'un profil minimal avec le pubkey
|
|
||||||
- Pas d'erreur si le profil n'existe pas
|
|
||||||
|
|
||||||
## Fichiers créés
|
|
||||||
|
|
||||||
### `hooks/useUserArticles.ts`
|
|
||||||
Hook personnalisé pour charger les articles d'un utilisateur spécifique :
|
|
||||||
- Filtre automatiquement les articles par `pubkey` de l'auteur
|
|
||||||
- Supporte la recherche et les filtres (comme `useArticles`)
|
|
||||||
- Gestion de l'état de chargement et des erreurs
|
|
||||||
- Méthode `loadArticleContent` pour charger le contenu privé
|
|
||||||
|
|
||||||
**Signature** :
|
|
||||||
```typescript
|
|
||||||
export function useUserArticles(
|
|
||||||
userPubkey: string,
|
|
||||||
searchQuery: string = '',
|
|
||||||
filters: ArticleFilters | null = null
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
### `components/UserProfile.tsx`
|
|
||||||
Composant d'affichage du profil utilisateur :
|
|
||||||
- Affichage de la photo de profil (ou initiale si pas de photo)
|
|
||||||
- Nom, pubkey tronqué, nip05
|
|
||||||
- Description/about si disponible
|
|
||||||
- Compteur d'articles publiés
|
|
||||||
|
|
||||||
**Props** :
|
|
||||||
```typescript
|
|
||||||
interface UserProfileProps {
|
|
||||||
profile: NostrProfile
|
|
||||||
pubkey: string
|
|
||||||
articleCount?: number
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `components/UserArticles.tsx`
|
|
||||||
Composant pour afficher la liste des articles de l'utilisateur :
|
|
||||||
- Réutilise `ArticleCard` pour la cohérence UI
|
|
||||||
- Gestion de l'état de chargement
|
|
||||||
- Gestion des erreurs
|
|
||||||
- Message si aucun article publié
|
|
||||||
- Gestion du déverrouillage des articles payants
|
|
||||||
|
|
||||||
**Props** :
|
|
||||||
```typescript
|
|
||||||
interface UserArticlesProps {
|
|
||||||
articles: Article[]
|
|
||||||
loading: boolean
|
|
||||||
error: string | null
|
|
||||||
onLoadContent: (articleId: string, authorPubkey: string) => Promise<Article | null>
|
|
||||||
showEmptyMessage?: boolean
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `pages/profile.tsx`
|
|
||||||
Page de profil utilisateur :
|
|
||||||
- Vérifie la connexion et redirige si non connecté
|
|
||||||
- Charge le profil de l'utilisateur connecté
|
|
||||||
- Affiche le profil avec `UserProfile`
|
|
||||||
- Affiche les articles avec recherche et filtres
|
|
||||||
- Header cohérent avec le reste de l'application
|
|
||||||
- Bouton retour vers la page d'accueil
|
|
||||||
|
|
||||||
## Fichiers modifiés
|
|
||||||
|
|
||||||
### `components/ConnectButton.tsx`
|
|
||||||
- Ajout d'un `Link` autour du nom/avatar de l'utilisateur
|
|
||||||
- Lien vers `/profile` pour accéder au profil
|
|
||||||
- Hover effect pour indiquer que c'est cliquable
|
|
||||||
|
|
||||||
**Changements** :
|
|
||||||
- Import de `Link` de `next/link`
|
|
||||||
- Le nom/avatar est maintenant dans un `Link` vers `/profile`
|
|
||||||
|
|
||||||
## Flux utilisateur
|
|
||||||
|
|
||||||
1. **Accès au profil** :
|
|
||||||
- L'utilisateur clique sur son nom/avatar dans le header
|
|
||||||
- Redirection vers `/profile`
|
|
||||||
- Si non connecté, redirection vers `/`
|
|
||||||
|
|
||||||
2. **Visualisation du profil** :
|
|
||||||
- Affichage des informations du profil
|
|
||||||
- Compteur d'articles publiés
|
|
||||||
|
|
||||||
3. **Gestion des articles** :
|
|
||||||
- Liste de tous les articles publiés
|
|
||||||
- Possibilité de rechercher et filtrer
|
|
||||||
- Possibilité de déverrouiller les articles payants (si l'utilisateur les a payés)
|
|
||||||
|
|
||||||
## Impact
|
|
||||||
|
|
||||||
### Utilisateur
|
|
||||||
- Accès facile à son profil et ses articles
|
|
||||||
- Vue d'ensemble de ses publications
|
|
||||||
- Recherche et filtres pour trouver rapidement un article spécifique
|
|
||||||
|
|
||||||
### Technique
|
|
||||||
- Code modulaire et réutilisable
|
|
||||||
- Hook personnalisé pour charger les articles par auteur
|
|
||||||
- Composants réutilisables (UserProfile, UserArticles)
|
|
||||||
- Cohérence UI avec le reste de l'application
|
|
||||||
|
|
||||||
## Limitations et améliorations futures
|
|
||||||
|
|
||||||
### Limitations actuelles
|
|
||||||
- Pas de statistiques détaillées (vues, paiements reçus)
|
|
||||||
- Pas d'édition/suppression d'articles
|
|
||||||
- Le profil ne peut être modifié que via Nostr (pas d'édition dans l'app)
|
|
||||||
|
|
||||||
### Améliorations possibles
|
|
||||||
- **Statistiques** : Ajouter un composant `ArticleStats` pour afficher :
|
|
||||||
- Nombre total de vues
|
|
||||||
- Nombre de paiements reçus
|
|
||||||
- Revenus totaux
|
|
||||||
- **Édition d'articles** : Permettre d'éditer/supprimer les articles publiés
|
|
||||||
- **Profil public** : Créer `/user/[pubkey]` pour voir le profil de n'importe quel utilisateur
|
|
||||||
- **Optimisation** : Filtrer les articles par auteur au niveau du relay (au lieu du client)
|
|
||||||
|
|
||||||
## Tests recommandés
|
|
||||||
|
|
||||||
1. **Accès au profil** :
|
|
||||||
- Se connecter et cliquer sur le nom/avatar
|
|
||||||
- Vérifier la redirection vers `/profile`
|
|
||||||
- Se déconnecter et essayer d'accéder à `/profile` directement
|
|
||||||
|
|
||||||
2. **Affichage du profil** :
|
|
||||||
- Vérifier l'affichage du nom, photo, description
|
|
||||||
- Vérifier le compteur d'articles
|
|
||||||
- Tester avec un profil qui n'a pas de photo/nom
|
|
||||||
|
|
||||||
3. **Articles** :
|
|
||||||
- Publier quelques articles et vérifier qu'ils apparaissent
|
|
||||||
- Tester la recherche et les filtres
|
|
||||||
- Vérifier le compteur d'articles
|
|
||||||
|
|
||||||
4. **Performance** :
|
|
||||||
- Tester avec un grand nombre d'articles
|
|
||||||
- Vérifier que le chargement n'est pas bloquant
|
|
||||||
Loading…
x
Reference in New Issue
Block a user