9.9 KiB
Payment Notes System
Author: Équipe 4NK Date: 2026-01-05 Status: Implemented
Overview
This document describes the implementation of explicit payment notes (kind 1) for all confirmed payments, in addition to zap receipts (kind 9735). These notes use the project's tag system and are automatically published after payment confirmation.
Motivations
- Transparency: Provide explicit, searchable payment records on Nostr
- Tag System Compliance: All payment notes use the project's standardized tag system
- Traceability: Enable easy querying and aggregation of payments
- User Experience: Users can see their payment history in their Nostr feed
Root Causes
- Zap receipts (kind 9735) are created by Lightning wallets and may not always include all project-specific tags
- Need for explicit payment records that follow the project's tag conventions
- Requirement to document all payment types (purchases, review tips, sponsoring) consistently
Implementation
1. Tag System Extension
New Payment Type
Added 'payment' to the TagType union in lib/nostrTagSystemTypes.ts:
export type TagType = 'author' | 'series' | 'publication' | 'quote' | 'payment'
PaymentTags Interface
New interface for payment notes:
export interface PaymentTags extends BaseTags {
type: 'payment'
paymentType: 'purchase' | 'review_tip' | 'sponsoring'
amount: number
payerPubkey: string
recipientPubkey: string
paymentHash: string
zapReceiptId?: string
articleId?: string
reviewId?: string
seriesId?: string
text?: string
}
Tag Builder
Added buildPaymentTags function in lib/nostrTagSystemBuild.ts to construct payment note tags:
kind_type: Payment type (purchase, review_tip, sponsoring)amount: Payment amount in satspayer: Payer's pubkeyrecipient: Recipient's pubkeypayment_hash: Payment hash or transaction IDzap_receipt: Zap receipt ID (if applicable)article: Article ID (if applicable)review_id: Review ID (if applicable)series: Series ID (if applicable)text: Optional plain text messagetransaction_id: Bitcoin transaction ID (for sponsoring)
2. Payment Notes Service
New file lib/paymentNotes.ts contains three main functions:
publishPurchaseNote
Publishes an explicit payment note for article purchases.
Parameters:
articleId: Article IDauthorPubkey: Author's pubkeypayerPubkey: Payer's pubkeyamount: Payment amount in satspaymentHash: Payment hash from zap receiptzapReceiptId: Zap receipt event ID (optional)category: Article categoryseriesId: Series ID (optional)payerPrivateKey: Payer's private key for signing
Process:
- Generates hash ID using
generatePurchaseHashId - Builds object ID with
buildObjectId - Constructs tags using
buildTagswithPaymentTags - Includes JSON metadata with full payment information
- Publishes kind 1 event with payment confirmation message
publishReviewTipNote
Publishes an explicit payment note for review tips.
Parameters:
articleId: Article IDreviewId: Review IDauthorPubkey: Author's pubkeyreviewerPubkey: Reviewer's pubkeypayerPubkey: Payer's pubkeyamount: Payment amount in satspaymentHash: Payment hash from zap receiptzapReceiptId: Zap receipt event ID (optional)category: Article categoryseriesId: Series ID (optional)text: Optional plain text messagepayerPrivateKey: Payer's private key for signing
Process:
- Generates hash ID using
generateReviewTipHashId - Builds object ID with
buildObjectId - Constructs tags using
buildTagswithPaymentTags - Includes JSON metadata with full tip information
- Publishes kind 1 event with tip confirmation message (includes text if provided)
publishSponsoringNote
Publishes an explicit payment note for sponsoring payments.
Parameters:
authorPubkey: Author's pubkeypayerPubkey: Payer's pubkeyamount: Payment amount in satspaymentHash: Payment hash or transaction IDcategory: Author category (optional)seriesId: Series ID (optional)articleId: Article ID (optional)text: Optional plain text messagetransactionId: Bitcoin transaction ID (optional)payerPrivateKey: Payer's private key for signing
Process:
- Generates hash ID using
generateSponsoringHashId - Builds object ID with
buildObjectId - Constructs tags using
buildTagswithPaymentTags - Adds
transaction_idtag if provided (for Bitcoin mainnet payments) - Includes JSON metadata with full sponsoring information
- Publishes kind 1 event with sponsoring confirmation message (includes text if provided)
3. Integration Points
Purchase Payments
File: lib/paymentPollingMain.ts
After a purchase payment is confirmed (zap receipt verified), the system:
- Sends private content to the user
- Tracks content delivery
- Triggers automatic transfer
- Publishes explicit payment note:
- Retrieves article information to get category and seriesId
- Gets zap receipt to extract payment hash
- Calls
publishPurchaseNotewith all relevant information
Error Handling: If note publication fails, the payment process continues (non-blocking).
Review Tips
File: components/ReviewTipForm.tsx
Review tips are handled via zap requests. The explicit note publication should be triggered after zap receipt confirmation. Currently, the zap request is published, and the actual payment is handled by Alby/WebLN.
Note: Review tip note publication should be integrated when zap receipt confirmation is implemented for review tips.
Sponsoring Payments
File: lib/sponsoringPaymentTracking.ts
After a sponsoring payment transaction is verified on Bitcoin mainnet, the system:
- Verifies the transaction
- Tracks the sponsoring payment
- Publishes explicit payment note (if payer information is available)
Note: Currently, sponsoring note publication requires payer information (pubkey, private key, category, text, etc.) which may not always be available at tracking time. This should be handled when the user submits the transaction ID.
4. Zap Receipt Queries
New file lib/zapReceiptQueries.ts provides:
getZapReceiptById
Retrieves a zap receipt event (kind 9735) by its ID.
Use Case: Extract payment hash and other information from zap receipts for payment note publication.
Tag Structure
Purchase Payment Note Tags
#payment
#sciencefiction or #research
#id_<hash>
#service_zapwall.fr
#version_0
#kind_type_purchase
#amount_<amount>
#payer_<payerPubkey>
#recipient_<authorPubkey>
#payment_hash_<paymentHash>
#zap_receipt_<zapReceiptId> (optional)
#article_<articleId>
#series_<seriesId> (optional)
#json_<JSON metadata>
Review Tip Payment Note Tags
#payment
#sciencefiction or #research
#id_<hash>
#service_zapwall.fr
#version_0
#kind_type_review_tip
#amount_<amount>
#payer_<payerPubkey>
#recipient_<reviewerPubkey>
#payment_hash_<paymentHash>
#zap_receipt_<zapReceiptId> (optional)
#article_<articleId>
#review_id_<reviewId>
#series_<seriesId> (optional)
#text_<text> (optional)
#json_<JSON metadata>
Sponsoring Payment Note Tags
#payment
#sciencefiction or #research
#id_<hash>
#service_zapwall.fr
#version_0
#kind_type_sponsoring
#amount_<amount>
#payer_<payerPubkey>
#recipient_<authorPubkey>
#payment_hash_<paymentHash>
#series_<seriesId> (optional)
#article_<articleId> (optional)
#text_<text> (optional)
#transaction_id_<transactionId> (optional, for Bitcoin mainnet)
#json_<JSON metadata>
JSON Metadata Structure
All payment notes include a json tag with complete payment information:
Purchase
{
"type": "purchase",
"id": "<hash>_0_0",
"hash": "<hash>",
"version": 0,
"index": 0,
"payerPubkey": "<pubkey>",
"articleId": "<articleId>",
"authorPubkey": "<pubkey>",
"amount": 800,
"paymentHash": "<hash>"
}
Review Tip
{
"type": "review_tip",
"id": "<hash>_0_0",
"hash": "<hash>",
"version": 0,
"index": 0,
"payerPubkey": "<pubkey>",
"articleId": "<articleId>",
"reviewId": "<reviewId>",
"reviewerPubkey": "<pubkey>",
"authorPubkey": "<pubkey>",
"amount": 100,
"paymentHash": "<hash>",
"text": "<optional text>"
}
Sponsoring
{
"type": "sponsoring",
"id": "<hash>_0_0",
"hash": "<hash>",
"version": 0,
"index": 0,
"payerPubkey": "<pubkey>",
"authorPubkey": "<pubkey>",
"amount": 4600000,
"paymentHash": "<hash>",
"seriesId": "<seriesId>",
"articleId": "<articleId>",
"text": "<optional text>",
"transactionId": "<transactionId>"
}
Error Handling
- Payment note publication failures do not block the payment process
- Errors are logged but do not prevent payment confirmation
- Users can still access content even if note publication fails
Future Improvements
- Review Tip Note Publication: Integrate automatic note publication after review tip zap receipt confirmation
- Sponsoring Note Publication: Improve integration to capture payer information at transaction submission time
- Payment History: Create UI to display user's payment history from payment notes
- Aggregation: Use payment notes for financial aggregations and statistics
- Search: Enable searching payment notes by various criteria (article, author, date, etc.)
Files Modified
lib/nostrTagSystemTypes.ts: AddedPaymentTagsinterfacelib/nostrTagSystemBuild.ts: AddedbuildPaymentTagsfunctionlib/paymentNotes.ts: New file with payment note publication functionslib/paymentPollingMain.ts: Integrated purchase note publicationlib/zapReceiptQueries.ts: New file for zap receipt querieslib/sponsoringPaymentTracking.ts: Prepared for sponsoring note publication (currently commented out)
Related Documentation
docs/object-identification-system.md: Object ID format and structuredocs/tag-system.md: Project tag system documentationdocs/payment-flows.md: Payment flow documentation