254 lines
7.3 KiB
TypeScript
254 lines
7.3 KiB
TypeScript
import { nostrService } from './nostr'
|
|
import { buildTags } from './nostrTagSystem'
|
|
import { PLATFORM_SERVICE } from './platformConfig'
|
|
import { generatePurchaseHashId, generateReviewTipHashId, generateSponsoringHashId } from './hashIdGenerator'
|
|
import { buildObjectId } from './urlGenerator'
|
|
import type { Event, EventTemplate } from 'nostr-tools'
|
|
|
|
/**
|
|
* Publish an explicit payment note (kind 1) for a purchase
|
|
* This note is published in addition to the zap receipt (kind 9735)
|
|
*/
|
|
export async function publishPurchaseNote(params: {
|
|
articleId: string
|
|
authorPubkey: string
|
|
payerPubkey: string
|
|
amount: number
|
|
paymentHash: string
|
|
zapReceiptId?: string
|
|
category?: 'science-fiction' | 'scientific-research'
|
|
seriesId?: string
|
|
payerPrivateKey: string
|
|
}): Promise<Event | null> {
|
|
let category: 'sciencefiction' | 'research' = 'sciencefiction'
|
|
if (params.category === 'science-fiction') {
|
|
category = 'sciencefiction'
|
|
} else if (params.category === 'scientific-research') {
|
|
category = 'research'
|
|
}
|
|
|
|
const purchaseData = {
|
|
payerPubkey: params.payerPubkey,
|
|
articleId: params.articleId,
|
|
authorPubkey: params.authorPubkey,
|
|
amount: params.amount,
|
|
paymentHash: params.paymentHash,
|
|
}
|
|
|
|
const hashId = await generatePurchaseHashId(purchaseData)
|
|
const id = buildObjectId(hashId, 0, 0)
|
|
|
|
const tags = buildTags({
|
|
type: 'payment',
|
|
category,
|
|
id: hashId,
|
|
service: PLATFORM_SERVICE,
|
|
version: 0,
|
|
hidden: false,
|
|
payment: true,
|
|
paymentType: 'purchase',
|
|
amount: params.amount,
|
|
payerPubkey: params.payerPubkey,
|
|
recipientPubkey: params.authorPubkey,
|
|
paymentHash: params.paymentHash,
|
|
articleId: params.articleId,
|
|
...(params.zapReceiptId ? { zapReceiptId: params.zapReceiptId } : {}),
|
|
...(params.seriesId ? { seriesId: params.seriesId } : {}),
|
|
})
|
|
|
|
// Build JSON metadata
|
|
const paymentJson = JSON.stringify({
|
|
type: 'purchase',
|
|
id,
|
|
hash: hashId,
|
|
version: 0,
|
|
index: 0,
|
|
...purchaseData,
|
|
})
|
|
|
|
tags.push(['json', paymentJson])
|
|
|
|
const eventTemplate: EventTemplate = {
|
|
kind: 1,
|
|
created_at: Math.floor(Date.now() / 1000),
|
|
tags,
|
|
content: `Purchase confirmed: ${params.amount} sats for article ${params.articleId}`,
|
|
}
|
|
|
|
nostrService.setPrivateKey(params.payerPrivateKey)
|
|
return nostrService.publishEvent(eventTemplate)
|
|
}
|
|
|
|
/**
|
|
* Publish an explicit payment note (kind 1) for a review tip
|
|
* This note is published in addition to the zap receipt (kind 9735)
|
|
*/
|
|
export async function publishReviewTipNote(params: {
|
|
articleId: string
|
|
reviewId: string
|
|
authorPubkey: string
|
|
reviewerPubkey: string
|
|
payerPubkey: string
|
|
amount: number
|
|
paymentHash: string
|
|
zapReceiptId?: string
|
|
category?: 'science-fiction' | 'scientific-research'
|
|
seriesId?: string
|
|
text?: string
|
|
payerPrivateKey: string
|
|
}): Promise<Event | null> {
|
|
let category: 'sciencefiction' | 'research' = 'sciencefiction'
|
|
if (params.category === 'science-fiction') {
|
|
category = 'sciencefiction'
|
|
} else if (params.category === 'scientific-research') {
|
|
category = 'research'
|
|
}
|
|
|
|
const tipData = {
|
|
payerPubkey: params.payerPubkey,
|
|
articleId: params.articleId,
|
|
reviewId: params.reviewId,
|
|
reviewerPubkey: params.reviewerPubkey,
|
|
authorPubkey: params.authorPubkey,
|
|
amount: params.amount,
|
|
paymentHash: params.paymentHash,
|
|
}
|
|
|
|
const hashId = await generateReviewTipHashId(tipData)
|
|
const id = buildObjectId(hashId, 0, 0)
|
|
|
|
const tags = buildTags({
|
|
type: 'payment',
|
|
category,
|
|
id: hashId,
|
|
service: PLATFORM_SERVICE,
|
|
version: 0,
|
|
hidden: false,
|
|
payment: true,
|
|
paymentType: 'review_tip',
|
|
amount: params.amount,
|
|
payerPubkey: params.payerPubkey,
|
|
recipientPubkey: params.reviewerPubkey,
|
|
paymentHash: params.paymentHash,
|
|
articleId: params.articleId,
|
|
reviewId: params.reviewId,
|
|
...(params.zapReceiptId ? { zapReceiptId: params.zapReceiptId } : {}),
|
|
...(params.seriesId ? { seriesId: params.seriesId } : {}),
|
|
...(params.text ? { text: params.text } : {}),
|
|
})
|
|
|
|
// Build JSON metadata
|
|
const paymentJson = JSON.stringify({
|
|
type: 'review_tip',
|
|
id,
|
|
hash: hashId,
|
|
version: 0,
|
|
index: 0,
|
|
...tipData,
|
|
...(params.text ? { text: params.text } : {}),
|
|
})
|
|
|
|
tags.push(['json', paymentJson])
|
|
|
|
const content = params.text
|
|
? `Review tip confirmed: ${params.amount} sats for review ${params.reviewId}\n\n${params.text}`
|
|
: `Review tip confirmed: ${params.amount} sats for review ${params.reviewId}`
|
|
|
|
const eventTemplate: EventTemplate = {
|
|
kind: 1,
|
|
created_at: Math.floor(Date.now() / 1000),
|
|
tags,
|
|
content,
|
|
}
|
|
|
|
nostrService.setPrivateKey(params.payerPrivateKey)
|
|
return nostrService.publishEvent(eventTemplate)
|
|
}
|
|
|
|
/**
|
|
* Publish an explicit payment note (kind 1) for a sponsoring
|
|
* This note is published in addition to the zap receipt (kind 9735) if applicable
|
|
*/
|
|
export async function publishSponsoringNote(params: {
|
|
authorPubkey: string
|
|
payerPubkey: string
|
|
amount: number
|
|
paymentHash: string
|
|
category?: 'science-fiction' | 'scientific-research'
|
|
seriesId?: string
|
|
articleId?: string
|
|
text?: string
|
|
transactionId?: string // Bitcoin transaction ID for mainnet payments
|
|
payerPrivateKey: string
|
|
}): Promise<Event | null> {
|
|
let category: 'sciencefiction' | 'research' = 'sciencefiction'
|
|
if (params.category === 'science-fiction') {
|
|
category = 'sciencefiction'
|
|
} else if (params.category === 'scientific-research') {
|
|
category = 'research'
|
|
}
|
|
|
|
const sponsoringData = {
|
|
payerPubkey: params.payerPubkey,
|
|
authorPubkey: params.authorPubkey,
|
|
amount: params.amount,
|
|
paymentHash: params.paymentHash,
|
|
...(params.seriesId ? { seriesId: params.seriesId } : {}),
|
|
...(params.articleId ? { articleId: params.articleId } : {}),
|
|
}
|
|
|
|
const hashId = await generateSponsoringHashId(sponsoringData)
|
|
const id = buildObjectId(hashId, 0, 0)
|
|
|
|
const tags = buildTags({
|
|
type: 'payment',
|
|
category,
|
|
id: hashId,
|
|
service: PLATFORM_SERVICE,
|
|
version: 0,
|
|
hidden: false,
|
|
payment: true,
|
|
paymentType: 'sponsoring',
|
|
amount: params.amount,
|
|
payerPubkey: params.payerPubkey,
|
|
recipientPubkey: params.authorPubkey,
|
|
paymentHash: params.paymentHash,
|
|
...(params.seriesId ? { seriesId: params.seriesId } : {}),
|
|
...(params.articleId ? { articleId: params.articleId } : {}),
|
|
...(params.text ? { text: params.text } : {}),
|
|
})
|
|
|
|
// Add transaction ID if provided (for Bitcoin mainnet payments)
|
|
if (params.transactionId) {
|
|
tags.push(['transaction_id', params.transactionId])
|
|
}
|
|
|
|
// Build JSON metadata
|
|
const paymentJson = JSON.stringify({
|
|
type: 'sponsoring',
|
|
id,
|
|
hash: hashId,
|
|
version: 0,
|
|
index: 0,
|
|
...sponsoringData,
|
|
...(params.text ? { text: params.text } : {}),
|
|
...(params.transactionId ? { transactionId: params.transactionId } : {}),
|
|
})
|
|
|
|
tags.push(['json', paymentJson])
|
|
|
|
const content = params.text
|
|
? `Sponsoring confirmed: ${params.amount} sats for author ${params.authorPubkey.substring(0, 16)}...\n\n${params.text}`
|
|
: `Sponsoring confirmed: ${params.amount} sats for author ${params.authorPubkey.substring(0, 16)}...`
|
|
|
|
const eventTemplate: EventTemplate = {
|
|
kind: 1,
|
|
created_at: Math.floor(Date.now() / 1000),
|
|
tags,
|
|
content,
|
|
}
|
|
|
|
nostrService.setPrivateKey(params.payerPrivateKey)
|
|
return nostrService.publishEvent(eventTemplate)
|
|
}
|