lint fix wip
This commit is contained in:
parent
38941147cb
commit
bb5cfa758c
@ -24,14 +24,14 @@ export function useArticlePayment(
|
||||
|
||||
const checkPaymentStatus = async (hash: string, userPubkey: string): Promise<void> => {
|
||||
try {
|
||||
const hasPaid = await paymentService.waitForArticlePayment(
|
||||
hash,
|
||||
article.id,
|
||||
article.pubkey,
|
||||
article.zapAmount,
|
||||
userPubkey,
|
||||
300000
|
||||
)
|
||||
const hasPaid = await paymentService.waitForArticlePayment({
|
||||
paymentHash: hash,
|
||||
articleId: article.id,
|
||||
articlePubkey: article.pubkey,
|
||||
amount: article.zapAmount,
|
||||
recipientPubkey: userPubkey,
|
||||
timeout: 300000,
|
||||
})
|
||||
|
||||
if (hasPaid) {
|
||||
const content = await nostrService.getPrivateContent(article.id, article.pubkey)
|
||||
|
||||
@ -48,16 +48,16 @@ export async function writeObjectToCache(params: WriteObjectParams): Promise<voi
|
||||
const tags = extractTagsFromEvent(event)
|
||||
const writeService = await getWriteService()
|
||||
|
||||
await writeService.writeObject(
|
||||
await writeService.writeObject({
|
||||
objectType,
|
||||
hash,
|
||||
event,
|
||||
parsed,
|
||||
version ?? tags.version ?? 0,
|
||||
hidden ?? tags.hidden ?? false,
|
||||
index ?? 0,
|
||||
published ?? false
|
||||
)
|
||||
version: version ?? tags.version ?? 0,
|
||||
hidden: hidden ?? tags.hidden ?? false,
|
||||
index: index ?? 0,
|
||||
published: published ?? false,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
26
lib/nostr.ts
26
lib/nostr.ts
@ -107,14 +107,23 @@ class NostrService {
|
||||
if (result.status === 'fulfilled') {
|
||||
successfulRelays.push(relayUrl)
|
||||
// Log successful publication
|
||||
void publishLog.logPublication(event.id, relayUrl, true, undefined)
|
||||
void publishLog.logPublication({
|
||||
eventId: event.id,
|
||||
relayUrl,
|
||||
success: true,
|
||||
})
|
||||
} else {
|
||||
const error = result.reason
|
||||
const errorMessage = error instanceof Error ? error.message : String(error)
|
||||
console.error(`[NostrService] Relay ${relayUrl} failed during publish:`, error)
|
||||
relaySessionManager.markRelayFailed(relayUrl)
|
||||
// Log failed publication
|
||||
void publishLog.logPublication(event.id, relayUrl, false, errorMessage)
|
||||
void publishLog.logPublication({
|
||||
eventId: event.id,
|
||||
relayUrl,
|
||||
success: false,
|
||||
error: errorMessage,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@ -143,14 +152,23 @@ class NostrService {
|
||||
if (result.status === 'fulfilled') {
|
||||
successfulRelays.push(relayUrl)
|
||||
// Log successful publication
|
||||
void publishLog.logPublication(event.id, relayUrl, true, undefined)
|
||||
void publishLog.logPublication({
|
||||
eventId: event.id,
|
||||
relayUrl,
|
||||
success: true,
|
||||
})
|
||||
} else {
|
||||
const error = result.reason
|
||||
const errorMessage = error instanceof Error ? error.message : String(error)
|
||||
console.error(`[NostrService] Relay ${relayUrl} failed during publish:`, error)
|
||||
relaySessionManager.markRelayFailed(relayUrl)
|
||||
// Log failed publication
|
||||
void publishLog.logPublication(event.id, relayUrl, false, errorMessage)
|
||||
void publishLog.logPublication({
|
||||
eventId: event.id,
|
||||
relayUrl,
|
||||
success: false,
|
||||
error: errorMessage,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@ -31,7 +31,13 @@ async function isValidZapReceipt(
|
||||
// Import verification service dynamically to avoid circular dependencies
|
||||
const { zapVerificationService } = await import('./zapVerification')
|
||||
|
||||
return zapVerificationService.verifyZapReceiptForArticle(params.event, params.targetEventId, params.targetPubkey, params.userPubkey, params.amount)
|
||||
return zapVerificationService.verifyZapReceiptForArticle({
|
||||
zapReceipt: params.event,
|
||||
articleId: params.targetEventId,
|
||||
articlePubkey: params.targetPubkey,
|
||||
userPubkey: params.userPubkey,
|
||||
expectedAmount: params.amount,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -75,7 +75,13 @@ class NotificationService {
|
||||
|
||||
// Utiliser writeService pour créer la notification via Web Worker
|
||||
const { writeService } = await import('./writeService')
|
||||
await writeService.createNotification(type, objectType, objectId, eventId, data)
|
||||
await writeService.createNotification({
|
||||
type,
|
||||
objectType,
|
||||
objectId,
|
||||
eventId,
|
||||
...(data !== undefined ? { data } : {}),
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('[NotificationService] Error creating notification:', error)
|
||||
}
|
||||
|
||||
@ -81,7 +81,7 @@ class ObjectCacheService {
|
||||
*/
|
||||
private async initDB(objectType: ObjectType): Promise<IDBDatabase> {
|
||||
const helper = this.getDBHelper(objectType)
|
||||
return await helper.init()
|
||||
return helper.init()
|
||||
}
|
||||
|
||||
/**
|
||||
@ -102,51 +102,52 @@ class ObjectCacheService {
|
||||
* Verifies and sets the index before insertion
|
||||
* @param published - false if not published, or array of relay URLs that successfully published
|
||||
*/
|
||||
async set(
|
||||
objectType: ObjectType,
|
||||
hash: string,
|
||||
event: NostrEvent,
|
||||
parsed: unknown,
|
||||
version: number,
|
||||
hidden: boolean,
|
||||
index?: number,
|
||||
published: false | string[] = false
|
||||
): Promise<void> {
|
||||
async set(params: {
|
||||
objectType: ObjectType
|
||||
hash: string
|
||||
event: NostrEvent
|
||||
parsed: unknown
|
||||
version: number
|
||||
hidden: boolean
|
||||
index?: number
|
||||
published?: false | string[]
|
||||
}): Promise<void> {
|
||||
try {
|
||||
const helper = this.getDBHelper(objectType)
|
||||
const helper = this.getDBHelper(params.objectType)
|
||||
|
||||
// If index is not provided, calculate it by counting objects with the same hash
|
||||
let finalIndex = index
|
||||
let finalIndex = params.index
|
||||
if (finalIndex === undefined) {
|
||||
const count = await this.countObjectsWithHash(objectType, hash)
|
||||
const count = await this.countObjectsWithHash(params.objectType, params.hash)
|
||||
finalIndex = count
|
||||
}
|
||||
|
||||
const id = buildObjectId(hash, finalIndex, version)
|
||||
const id = buildObjectId(params.hash, finalIndex, params.version)
|
||||
|
||||
// Check if object already exists to preserve published status if updating
|
||||
const existing = await helper.get<CachedObject>(id).catch(() => null)
|
||||
|
||||
// If updating and published is not provided, preserve existing published status
|
||||
const published = params.published ?? false
|
||||
const finalPublished = existing && published === false ? existing.published : published
|
||||
|
||||
const cached: CachedObject = {
|
||||
id,
|
||||
hash,
|
||||
hashId: hash, // Legacy field for backward compatibility
|
||||
hash: params.hash,
|
||||
hashId: params.hash, // Legacy field for backward compatibility
|
||||
index: finalIndex,
|
||||
event,
|
||||
parsed,
|
||||
version,
|
||||
hidden,
|
||||
createdAt: event.created_at,
|
||||
event: params.event,
|
||||
parsed: params.parsed,
|
||||
version: params.version,
|
||||
hidden: params.hidden,
|
||||
createdAt: params.event.created_at,
|
||||
cachedAt: Date.now(),
|
||||
published: finalPublished,
|
||||
}
|
||||
|
||||
await helper.put(cached)
|
||||
} catch (cacheError) {
|
||||
console.error(`Error caching ${objectType} object:`, cacheError)
|
||||
console.error(`Error caching ${params.objectType} object:`, cacheError)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -81,21 +81,21 @@ export class PaymentService {
|
||||
/**
|
||||
* Check if payment for an article has been completed
|
||||
*/
|
||||
async checkArticlePayment(
|
||||
_paymentHash: string,
|
||||
articleId: string,
|
||||
articlePubkey: string,
|
||||
amount: number,
|
||||
async checkArticlePayment(params: {
|
||||
paymentHash: string
|
||||
articleId: string
|
||||
articlePubkey: string
|
||||
amount: number
|
||||
userPubkey?: string
|
||||
): Promise<boolean> {
|
||||
}): Promise<boolean> {
|
||||
try {
|
||||
// With Alby/WebLN, we rely on zap receipts for payment verification
|
||||
// since WebLN doesn't provide payment status checking
|
||||
const zapReceiptExists = await nostrService.checkZapReceipt(
|
||||
articlePubkey,
|
||||
articleId,
|
||||
amount,
|
||||
userPubkey
|
||||
params.articlePubkey,
|
||||
params.articleId,
|
||||
params.amount,
|
||||
params.userPubkey
|
||||
)
|
||||
|
||||
return zapReceiptExists
|
||||
@ -109,22 +109,22 @@ export class PaymentService {
|
||||
* Wait for payment completion with polling
|
||||
* After payment is confirmed, sends private content to the user
|
||||
*/
|
||||
waitForArticlePayment(
|
||||
paymentHash: string,
|
||||
articleId: string,
|
||||
articlePubkey: string,
|
||||
amount: number,
|
||||
recipientPubkey: string,
|
||||
timeout: number = 300000 // 5 minutes
|
||||
): Promise<boolean> {
|
||||
return waitForArticlePaymentHelper(
|
||||
paymentHash,
|
||||
articleId,
|
||||
articlePubkey,
|
||||
amount,
|
||||
recipientPubkey,
|
||||
timeout
|
||||
)
|
||||
waitForArticlePayment(params: {
|
||||
paymentHash: string
|
||||
articleId: string
|
||||
articlePubkey: string
|
||||
amount: number
|
||||
recipientPubkey: string
|
||||
timeout?: number
|
||||
}): Promise<boolean> {
|
||||
return waitForArticlePaymentHelper({
|
||||
paymentHash: params.paymentHash,
|
||||
articleId: params.articleId,
|
||||
articlePubkey: params.articlePubkey,
|
||||
amount: params.amount,
|
||||
recipientPubkey: params.recipientPubkey,
|
||||
...(params.timeout !== undefined ? { timeout: params.timeout } : {}),
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -7,49 +7,61 @@ import { sendPrivateContentAfterPayment } from './paymentPollingMain'
|
||||
* After payment is confirmed, sends private content to the user
|
||||
*/
|
||||
async function pollPaymentUntilDeadline(
|
||||
articleId: string,
|
||||
articlePubkey: string,
|
||||
amount: number,
|
||||
recipientPubkey: string,
|
||||
interval: number,
|
||||
deadline: number
|
||||
params: {
|
||||
articleId: string
|
||||
articlePubkey: string
|
||||
amount: number
|
||||
recipientPubkey: string
|
||||
interval: number
|
||||
deadline: number
|
||||
}
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
const zapReceiptExists = await nostrService.checkZapReceipt(articlePubkey, articleId, amount, recipientPubkey)
|
||||
const zapReceiptExists = await nostrService.checkZapReceipt(params.articlePubkey, params.articleId, params.amount, params.recipientPubkey)
|
||||
if (zapReceiptExists) {
|
||||
const zapReceiptId = await getZapReceiptId(articlePubkey, articleId, amount, recipientPubkey)
|
||||
await sendPrivateContentAfterPayment(articleId, recipientPubkey, amount, zapReceiptId)
|
||||
const zapReceiptId = await getZapReceiptId(params.articlePubkey, params.articleId, params.amount, params.recipientPubkey)
|
||||
await sendPrivateContentAfterPayment(params.articleId, params.recipientPubkey, params.amount, zapReceiptId)
|
||||
return true
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error checking zap receipt:', error)
|
||||
}
|
||||
|
||||
if (Date.now() > deadline) {
|
||||
if (Date.now() > params.deadline) {
|
||||
return false
|
||||
}
|
||||
|
||||
return new Promise<boolean>((resolve) => {
|
||||
setTimeout(() => {
|
||||
void pollPaymentUntilDeadline(articleId, articlePubkey, amount, recipientPubkey, interval, deadline)
|
||||
void pollPaymentUntilDeadline(params)
|
||||
.then(resolve)
|
||||
.catch(() => resolve(false))
|
||||
}, interval)
|
||||
}, params.interval)
|
||||
})
|
||||
}
|
||||
|
||||
export async function waitForArticlePayment(
|
||||
_paymentHash: string,
|
||||
articleId: string,
|
||||
articlePubkey: string,
|
||||
amount: number,
|
||||
recipientPubkey: string,
|
||||
timeout: number = 300000 // 5 minutes
|
||||
params: {
|
||||
paymentHash: string
|
||||
articleId: string
|
||||
articlePubkey: string
|
||||
amount: number
|
||||
recipientPubkey: string
|
||||
timeout?: number
|
||||
}
|
||||
): Promise<boolean> {
|
||||
const interval = 2000
|
||||
const timeout = params.timeout ?? 300000
|
||||
const deadline = Date.now() + timeout
|
||||
try {
|
||||
return pollPaymentUntilDeadline(articleId, articlePubkey, amount, recipientPubkey, interval, deadline)
|
||||
return pollPaymentUntilDeadline({
|
||||
articleId: params.articleId,
|
||||
articlePubkey: params.articlePubkey,
|
||||
amount: params.amount,
|
||||
recipientPubkey: params.recipientPubkey,
|
||||
interval,
|
||||
deadline,
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Wait for payment error:', error)
|
||||
return false
|
||||
|
||||
@ -19,6 +19,15 @@ interface PublicationLogEntry {
|
||||
objectId?: string // ID of the object in cache
|
||||
}
|
||||
|
||||
interface LogPublicationParams {
|
||||
eventId: string
|
||||
relayUrl: string
|
||||
success: boolean
|
||||
error?: string
|
||||
objectType?: string
|
||||
objectId?: string
|
||||
}
|
||||
|
||||
class PublishLogService {
|
||||
private readonly dbHelper: IndexedDBHelper
|
||||
|
||||
@ -52,17 +61,10 @@ class PublishLogService {
|
||||
* Log a publication attempt
|
||||
* Utilise writeService pour écrire via Web Worker
|
||||
*/
|
||||
async logPublication(
|
||||
eventId: string,
|
||||
relayUrl: string,
|
||||
success: boolean,
|
||||
error?: string,
|
||||
objectType?: string,
|
||||
objectId?: string
|
||||
): Promise<void> {
|
||||
async logPublication(params: LogPublicationParams): Promise<void> {
|
||||
// Utiliser writeService pour logger via Web Worker
|
||||
const { writeService } = await import('./writeService')
|
||||
await writeService.logPublication(eventId, relayUrl, success, error, objectType, objectId)
|
||||
await writeService.logPublication(params)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -70,24 +72,17 @@ class PublishLogService {
|
||||
* @deprecated Utiliser logPublication qui utilise writeService
|
||||
* @internal Utilisé uniquement par writeService en fallback
|
||||
*/
|
||||
async logPublicationDirect(
|
||||
eventId: string,
|
||||
relayUrl: string,
|
||||
success: boolean,
|
||||
error?: string,
|
||||
objectType?: string,
|
||||
objectId?: string
|
||||
): Promise<void> {
|
||||
async logPublicationDirect(params: LogPublicationParams): Promise<void> {
|
||||
try {
|
||||
const entry: PublicationLogEntry = {
|
||||
id: `${eventId}_${relayUrl}_${Date.now()}`, // Unique ID
|
||||
eventId,
|
||||
relayUrl,
|
||||
success,
|
||||
...(error !== undefined ? { error } : {}),
|
||||
id: `${params.eventId}_${params.relayUrl}_${Date.now()}`, // Unique ID
|
||||
eventId: params.eventId,
|
||||
relayUrl: params.relayUrl,
|
||||
success: params.success,
|
||||
...(params.error !== undefined ? { error: params.error } : {}),
|
||||
timestamp: Date.now(),
|
||||
...(objectType !== undefined ? { objectType } : {}),
|
||||
...(objectId !== undefined ? { objectId } : {}),
|
||||
...(params.objectType !== undefined ? { objectType: params.objectType } : {}),
|
||||
...(params.objectId !== undefined ? { objectId: params.objectId } : {}),
|
||||
}
|
||||
|
||||
await this.dbHelper.add(entry)
|
||||
|
||||
@ -179,13 +179,26 @@ class PublishWorkerService {
|
||||
if (status.success) {
|
||||
successfulRelays.push(relayUrl)
|
||||
// Log successful publication
|
||||
void publishLog.logPublication(obj.event.id, relayUrl, true, undefined, obj.objectType, obj.id)
|
||||
void publishLog.logPublication({
|
||||
eventId: obj.event.id,
|
||||
relayUrl,
|
||||
success: true,
|
||||
objectType: obj.objectType,
|
||||
objectId: obj.id,
|
||||
})
|
||||
} else {
|
||||
const errorMessage = status.error ?? 'Unknown error'
|
||||
console.warn(`[PublishWorker] Relay ${relayUrl} failed for ${obj.objectType}:${obj.id}:`, errorMessage)
|
||||
relaySessionManager.markRelayFailed(relayUrl)
|
||||
// Log failed publication
|
||||
void publishLog.logPublication(obj.event.id, relayUrl, false, errorMessage, obj.objectType, obj.id)
|
||||
void publishLog.logPublication({
|
||||
eventId: obj.event.id,
|
||||
relayUrl,
|
||||
success: false,
|
||||
error: errorMessage,
|
||||
objectType: obj.objectType,
|
||||
objectId: obj.id,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ import { getCachedObjectById } from './helpers/queryHelpers'
|
||||
import { objectCache } from './objectCache'
|
||||
|
||||
export async function getPurchaseById(purchaseId: string, _timeoutMs: number = 5000): Promise<Purchase | null> {
|
||||
return await getCachedObjectById<Purchase>('purchase', purchaseId)
|
||||
return getCachedObjectById<Purchase>('purchase', purchaseId)
|
||||
}
|
||||
|
||||
export async function getPurchasesForArticle(articleId: string, _timeoutMs: number = 5000): Promise<Purchase[]> {
|
||||
|
||||
@ -3,7 +3,7 @@ import { objectCache } from './objectCache'
|
||||
import { getCachedObjectById } from './helpers/queryHelpers'
|
||||
|
||||
export async function getReviewTipById(reviewTipId: string, _timeoutMs: number = 5000): Promise<ReviewTip | null> {
|
||||
return await getCachedObjectById<ReviewTip>('review_tip', reviewTipId)
|
||||
return getCachedObjectById<ReviewTip>('review_tip', reviewTipId)
|
||||
}
|
||||
|
||||
export async function getReviewTipsForArticle(articleId: string, _timeoutMs: number = 5000): Promise<ReviewTip[]> {
|
||||
|
||||
@ -22,5 +22,5 @@ export async function getSeriesByAuthor(authorPubkey: string, _timeoutMs: number
|
||||
}
|
||||
|
||||
export async function getSeriesById(seriesId: string, _timeoutMs: number = 2000): Promise<Series | null> {
|
||||
return await getCachedObjectById<Series>('series', seriesId)
|
||||
return getCachedObjectById<Series>('series', seriesId)
|
||||
}
|
||||
|
||||
@ -28,11 +28,13 @@ export async function verifyTransactionBeforeTracking(
|
||||
}
|
||||
|
||||
export function buildTrackingData(
|
||||
transactionId: string,
|
||||
authorPubkey: string,
|
||||
authorMainnetAddress: string,
|
||||
split: { total: number; authorSats: number; platformSats: number },
|
||||
verification: { confirmed: boolean; confirmations: number }
|
||||
params: {
|
||||
transactionId: string
|
||||
authorPubkey: string
|
||||
authorMainnetAddress: string
|
||||
split: { total: number; authorSats: number; platformSats: number; authorMainnetAddress?: string }
|
||||
verification: { confirmed: boolean; confirmations: number }
|
||||
}
|
||||
): {
|
||||
transactionId: string
|
||||
authorPubkey: string
|
||||
@ -45,15 +47,15 @@ export function buildTrackingData(
|
||||
confirmations: number
|
||||
} {
|
||||
return {
|
||||
transactionId,
|
||||
authorPubkey,
|
||||
authorMainnetAddress,
|
||||
amount: split.total,
|
||||
authorAmount: split.authorSats,
|
||||
platformCommission: split.platformSats,
|
||||
transactionId: params.transactionId,
|
||||
authorPubkey: params.authorPubkey,
|
||||
authorMainnetAddress: params.authorMainnetAddress,
|
||||
amount: params.split.total,
|
||||
authorAmount: params.split.authorSats,
|
||||
platformCommission: params.split.platformSats,
|
||||
timestamp: Math.floor(Date.now() / 1000),
|
||||
confirmed: verification.confirmed,
|
||||
confirmations: verification.confirmations,
|
||||
confirmed: params.verification.confirmed,
|
||||
confirmations: params.verification.confirmations,
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,11 +91,13 @@ export async function trackSponsoringPayment(
|
||||
}
|
||||
|
||||
const trackingData = buildTrackingData(
|
||||
transactionId,
|
||||
authorPubkey,
|
||||
authorMainnetAddress,
|
||||
split,
|
||||
verification
|
||||
{
|
||||
transactionId,
|
||||
authorPubkey,
|
||||
authorMainnetAddress,
|
||||
split,
|
||||
verification,
|
||||
}
|
||||
)
|
||||
|
||||
await sponsoringTrackingService.trackSponsoringPayment(trackingData, authorPrivateKey)
|
||||
|
||||
@ -3,7 +3,7 @@ import { objectCache } from './objectCache'
|
||||
import { getCachedObjectById } from './helpers/queryHelpers'
|
||||
|
||||
export async function getSponsoringById(sponsoringId: string, _timeoutMs: number = 5000): Promise<Sponsoring | null> {
|
||||
return await getCachedObjectById<Sponsoring>('sponsoring', sponsoringId)
|
||||
return getCachedObjectById<Sponsoring>('sponsoring', sponsoringId)
|
||||
}
|
||||
|
||||
export async function getSponsoringByAuthor(authorPubkey: string, _timeoutMs: number = 5000): Promise<Sponsoring[]> {
|
||||
|
||||
@ -152,12 +152,21 @@ class ServiceWorkerSyncHandler {
|
||||
if (status.success) {
|
||||
successfulRelays.push(relayUrl)
|
||||
// Log successful publication
|
||||
void publishLog.logPublication(event.id, relayUrl, true, undefined)
|
||||
void publishLog.logPublication({
|
||||
eventId: event.id,
|
||||
relayUrl,
|
||||
success: true,
|
||||
})
|
||||
} else {
|
||||
const errorMessage = status.error ?? 'Unknown error'
|
||||
console.error(`[SWSyncHandler] Relay ${relayUrl} failed:`, errorMessage)
|
||||
// Log failed publication
|
||||
void publishLog.logPublication(event.id, relayUrl, false, errorMessage)
|
||||
void publishLog.logPublication({
|
||||
eventId: event.id,
|
||||
relayUrl,
|
||||
success: false,
|
||||
error: errorMessage,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@ -53,7 +53,16 @@ class WriteOrchestrator {
|
||||
.filter((relay): relay is string => relay !== null)
|
||||
}),
|
||||
// 2. Write to IndexedDB via Web Worker (en parallèle, avec published: false initialement)
|
||||
writeService.writeObject(objectType, hash, event, parsed, version, hidden, index, false),
|
||||
writeService.writeObject({
|
||||
objectType,
|
||||
hash,
|
||||
event,
|
||||
parsed,
|
||||
version,
|
||||
hidden,
|
||||
...(index !== undefined ? { index } : {}),
|
||||
published: false,
|
||||
}),
|
||||
])
|
||||
|
||||
// Traiter le résultat réseau
|
||||
@ -85,24 +94,24 @@ class WriteOrchestrator {
|
||||
/**
|
||||
* Create and publish event from template
|
||||
*/
|
||||
async createAndPublishEvent(
|
||||
eventTemplate: EventTemplate,
|
||||
relays: string[],
|
||||
objectType: ObjectType,
|
||||
hash: string,
|
||||
parsed: unknown,
|
||||
version: number,
|
||||
hidden: boolean,
|
||||
async createAndPublishEvent(params: {
|
||||
eventTemplate: EventTemplate
|
||||
relays: string[]
|
||||
objectType: ObjectType
|
||||
hash: string
|
||||
parsed: unknown
|
||||
version: number
|
||||
hidden: boolean
|
||||
index?: number
|
||||
): Promise<{ success: boolean; event: NostrEvent; published: false | string[] }> {
|
||||
}): Promise<{ success: boolean; event: NostrEvent; published: false | string[] }> {
|
||||
if (!this.privateKey) {
|
||||
throw new Error('Private key not set')
|
||||
}
|
||||
|
||||
// Create event
|
||||
const unsignedEvent: EventTemplate = {
|
||||
...eventTemplate,
|
||||
created_at: eventTemplate.created_at ?? Math.floor(Date.now() / 1000),
|
||||
...params.eventTemplate,
|
||||
created_at: params.eventTemplate.created_at ?? Math.floor(Date.now() / 1000),
|
||||
}
|
||||
|
||||
const secretKey = hexToBytes(this.privateKey)
|
||||
@ -111,15 +120,15 @@ class WriteOrchestrator {
|
||||
// Write and publish
|
||||
const result = await this.writeAndPublish(
|
||||
{
|
||||
objectType,
|
||||
hash,
|
||||
objectType: params.objectType,
|
||||
hash: params.hash,
|
||||
event: finalizedEvent,
|
||||
parsed,
|
||||
version,
|
||||
hidden,
|
||||
...(index !== undefined ? { index } : {}),
|
||||
parsed: params.parsed,
|
||||
version: params.version,
|
||||
hidden: params.hidden,
|
||||
...(params.index !== undefined ? { index: params.index } : {}),
|
||||
},
|
||||
relays
|
||||
params.relays
|
||||
)
|
||||
|
||||
return {
|
||||
|
||||
@ -7,6 +7,34 @@
|
||||
import type { NostrEvent } from 'nostr-tools'
|
||||
import type { ObjectType } from './objectCache'
|
||||
|
||||
interface WriteObjectParams {
|
||||
objectType: ObjectType
|
||||
hash: string
|
||||
event: NostrEvent
|
||||
parsed: unknown
|
||||
version: number
|
||||
hidden: boolean
|
||||
index?: number
|
||||
published?: false | string[]
|
||||
}
|
||||
|
||||
interface CreateNotificationParams {
|
||||
type: string
|
||||
objectType: string
|
||||
objectId: string
|
||||
eventId: string
|
||||
data?: Record<string, unknown>
|
||||
}
|
||||
|
||||
interface LogPublicationParams {
|
||||
eventId: string
|
||||
relayUrl: string
|
||||
success: boolean
|
||||
error?: string
|
||||
objectType?: string
|
||||
objectId?: string
|
||||
}
|
||||
|
||||
class WriteService {
|
||||
private writeWorker: Worker | null = null
|
||||
private initPromise: Promise<void> | null = null
|
||||
@ -91,19 +119,12 @@ class WriteService {
|
||||
/**
|
||||
* Write object to IndexedDB (via Web Worker)
|
||||
*/
|
||||
async writeObject(
|
||||
objectType: ObjectType,
|
||||
hash: string,
|
||||
event: NostrEvent,
|
||||
parsed: unknown,
|
||||
version: number,
|
||||
hidden: boolean,
|
||||
index?: number,
|
||||
published: false | string[] = false
|
||||
): Promise<void> {
|
||||
async writeObject(params: WriteObjectParams): Promise<void> {
|
||||
try {
|
||||
await this.init()
|
||||
|
||||
const published = params.published ?? false
|
||||
|
||||
if (this.writeWorker) {
|
||||
// Send to worker
|
||||
return new Promise((resolve, reject) => {
|
||||
@ -113,7 +134,7 @@ class WriteService {
|
||||
|
||||
const handler = (event: MessageEvent): void => {
|
||||
const { type, data } = event.data
|
||||
if (type === 'WRITE_OBJECT_SUCCESS' && data.hash === hash) {
|
||||
if (type === 'WRITE_OBJECT_SUCCESS' && data.hash === params.hash) {
|
||||
clearTimeout(timeout)
|
||||
this.writeWorker?.removeEventListener('message', handler)
|
||||
resolve()
|
||||
@ -129,13 +150,13 @@ class WriteService {
|
||||
this.writeWorker.postMessage({
|
||||
type: 'WRITE_OBJECT',
|
||||
data: {
|
||||
objectType,
|
||||
hash,
|
||||
event,
|
||||
parsed,
|
||||
version,
|
||||
hidden,
|
||||
index,
|
||||
objectType: params.objectType,
|
||||
hash: params.hash,
|
||||
event: params.event,
|
||||
parsed: params.parsed,
|
||||
version: params.version,
|
||||
hidden: params.hidden,
|
||||
index: params.index,
|
||||
published,
|
||||
},
|
||||
})
|
||||
@ -144,7 +165,16 @@ class WriteService {
|
||||
}
|
||||
// Fallback: direct write
|
||||
const { objectCache } = await import('./objectCache')
|
||||
await objectCache.set(objectType, hash, event, parsed, version, hidden, index, published)
|
||||
await objectCache.set({
|
||||
objectType: params.objectType,
|
||||
hash: params.hash,
|
||||
event: params.event,
|
||||
parsed: params.parsed,
|
||||
version: params.version,
|
||||
hidden: params.hidden,
|
||||
...(params.index !== undefined ? { index: params.index } : {}),
|
||||
...(params.published !== undefined ? { published: params.published } : {}),
|
||||
})
|
||||
|
||||
} catch (error) {
|
||||
console.error('[WriteService] Error writing object:', error)
|
||||
@ -205,13 +235,7 @@ class WriteService {
|
||||
/**
|
||||
* Create notification (via Web Worker)
|
||||
*/
|
||||
async createNotification(
|
||||
type: string,
|
||||
objectType: string,
|
||||
objectId: string,
|
||||
eventId: string,
|
||||
data?: Record<string, unknown>
|
||||
): Promise<void> {
|
||||
async createNotification(params: CreateNotificationParams): Promise<void> {
|
||||
try {
|
||||
await this.init()
|
||||
|
||||
@ -224,7 +248,7 @@ class WriteService {
|
||||
|
||||
const handler = (event: MessageEvent): void => {
|
||||
const { type: responseType, data: responseData } = event.data
|
||||
if (responseType === 'CREATE_NOTIFICATION_SUCCESS' && responseData.eventId === eventId) {
|
||||
if (responseType === 'CREATE_NOTIFICATION_SUCCESS' && responseData.eventId === params.eventId) {
|
||||
clearTimeout(timeout)
|
||||
this.writeWorker?.removeEventListener('message', handler)
|
||||
resolve()
|
||||
@ -239,7 +263,13 @@ class WriteService {
|
||||
this.writeWorker.addEventListener('message', handler)
|
||||
this.writeWorker.postMessage({
|
||||
type: 'CREATE_NOTIFICATION',
|
||||
data: { type, objectType, objectId, eventId, notificationData: data },
|
||||
data: {
|
||||
type: params.type,
|
||||
objectType: params.objectType,
|
||||
objectId: params.objectId,
|
||||
eventId: params.eventId,
|
||||
notificationData: params.data,
|
||||
},
|
||||
})
|
||||
}
|
||||
})
|
||||
@ -247,13 +277,13 @@ class WriteService {
|
||||
// Fallback: direct write
|
||||
const { notificationService } = await import('./notificationService')
|
||||
const notificationParams: Parameters<typeof notificationService.createNotification>[0] = {
|
||||
type: type as Parameters<typeof notificationService.createNotification>[0]['type'],
|
||||
objectType,
|
||||
objectId,
|
||||
eventId,
|
||||
type: params.type as Parameters<typeof notificationService.createNotification>[0]['type'],
|
||||
objectType: params.objectType,
|
||||
objectId: params.objectId,
|
||||
eventId: params.eventId,
|
||||
}
|
||||
if (data !== undefined) {
|
||||
notificationParams.data = data
|
||||
if (params.data !== undefined) {
|
||||
notificationParams.data = params.data
|
||||
}
|
||||
await notificationService.createNotification(notificationParams)
|
||||
|
||||
@ -267,14 +297,7 @@ class WriteService {
|
||||
/**
|
||||
* Log publication (via Web Worker)
|
||||
*/
|
||||
async logPublication(
|
||||
eventId: string,
|
||||
relayUrl: string,
|
||||
success: boolean,
|
||||
error?: string,
|
||||
objectType?: string,
|
||||
objectId?: string
|
||||
): Promise<void> {
|
||||
async logPublication(params: LogPublicationParams): Promise<void> {
|
||||
try {
|
||||
await this.init()
|
||||
|
||||
@ -282,13 +305,20 @@ class WriteService {
|
||||
// Send to worker
|
||||
this.writeWorker.postMessage({
|
||||
type: 'LOG_PUBLICATION',
|
||||
data: { eventId, relayUrl, success, error, objectType, objectId },
|
||||
data: {
|
||||
eventId: params.eventId,
|
||||
relayUrl: params.relayUrl,
|
||||
success: params.success,
|
||||
error: params.error,
|
||||
objectType: params.objectType,
|
||||
objectId: params.objectId,
|
||||
},
|
||||
})
|
||||
// Don't wait for response for logs (fire and forget)
|
||||
} else {
|
||||
// Fallback: direct write
|
||||
const { publishLog } = await import('./publishLog')
|
||||
await publishLog.logPublicationDirect(eventId, relayUrl, success, error, objectType, objectId)
|
||||
await publishLog.logPublicationDirect(params)
|
||||
}
|
||||
} catch (logError) {
|
||||
console.error('[WriteService] Error logging publication:', logError)
|
||||
|
||||
@ -19,23 +19,23 @@ export class ZapVerificationService {
|
||||
/**
|
||||
* Check if a zap receipt is valid for a specific article and user
|
||||
*/
|
||||
verifyZapReceiptForArticle(
|
||||
zapReceipt: Event,
|
||||
articleId: string,
|
||||
articlePubkey: string,
|
||||
_userPubkey: string,
|
||||
verifyZapReceiptForArticle(params: {
|
||||
zapReceipt: Event
|
||||
articleId: string
|
||||
articlePubkey: string
|
||||
userPubkey: string
|
||||
expectedAmount: number
|
||||
): boolean {
|
||||
if (!this.verifyZapReceiptSignature(zapReceipt)) {
|
||||
}): boolean {
|
||||
if (!this.verifyZapReceiptSignature(params.zapReceipt)) {
|
||||
console.warn('Zap receipt signature verification failed')
|
||||
return false
|
||||
}
|
||||
|
||||
return (
|
||||
this.isRecipientValid(zapReceipt, articlePubkey) &&
|
||||
this.isArticleReferenced(zapReceipt, articleId) &&
|
||||
this.isAmountValid(zapReceipt, expectedAmount) &&
|
||||
this.isZapKind(zapReceipt)
|
||||
this.isRecipientValid(params.zapReceipt, params.articlePubkey) &&
|
||||
this.isArticleReferenced(params.zapReceipt, params.articleId) &&
|
||||
this.isAmountValid(params.zapReceipt, params.expectedAmount) &&
|
||||
this.isZapKind(params.zapReceipt)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user