+
+
+ Invalid Market Product
+
+
+ {{ formatDistanceToNow(note.created_at * 1000, { addSuffix: true }) }}
+
+
+
+ Unable to parse market product data
+
+
+
+
+
+
+ Admin
+
+
+ Reply
+
+
+ {{ getMarketEventType({ kind: note.kind }) }}
+
+
+ {{ formatDistanceToNow(note.created_at * 1000, { addSuffix: true }) }}
+
+
+
-
-
-
-
Mentions:
-
- {{ mention.slice(0, 8) }}...
-
-
- +{{ note.mentions.length - 3 }} more
-
+
+
+ {{ note.content }}
+
+
+
+
+
+ Mentions:
+
+ {{ mention.slice(0, 8) }}...
+
+
+ +{{ note.mentions.length - 3 }} more
+
+
diff --git a/src/modules/nostr-feed/utils/marketParser.ts b/src/modules/nostr-feed/utils/marketParser.ts
new file mode 100644
index 0000000..1c2e807
--- /dev/null
+++ b/src/modules/nostr-feed/utils/marketParser.ts
@@ -0,0 +1,101 @@
+import type { Event as NostrEvent } from 'nostr-tools'
+import type { MarketProductData } from '../components/MarketProduct.vue'
+
+export interface MarketStallData {
+ id: string
+ name: string
+ description: string
+ currency: string
+ shipping: Array<{
+ id: string
+ cost: number
+ }>
+}
+
+/**
+ * Parse a Nostr market product event (kind 30018) into structured data
+ */
+export function parseMarketProduct(event: NostrEvent): MarketProductData | null {
+ try {
+ if (event.kind !== 30018) {
+ return null
+ }
+
+ // Parse the JSON content
+ const productData = JSON.parse(event.content)
+
+ // Validate required fields
+ if (!productData.id || !productData.name || typeof productData.price !== 'number') {
+ console.warn('Invalid market product data:', productData)
+ return null
+ }
+
+ return {
+ id: productData.id,
+ stall_id: productData.stall_id || '',
+ name: productData.name,
+ description: productData.description || '',
+ images: Array.isArray(productData.images) ? productData.images : [],
+ currency: productData.currency || 'sat',
+ price: productData.price,
+ quantity: productData.quantity || 0,
+ active: productData.active !== false, // Default to true if not specified
+ shipping: Array.isArray(productData.shipping) ? productData.shipping : []
+ }
+ } catch (error) {
+ console.error('Failed to parse market product event:', error, event)
+ return null
+ }
+}
+
+/**
+ * Parse a Nostr market stall event (kind 30017) into structured data
+ */
+export function parseMarketStall(event: NostrEvent): MarketStallData | null {
+ try {
+ if (event.kind !== 30017) {
+ return null
+ }
+
+ const stallData = JSON.parse(event.content)
+
+ if (!stallData.id || !stallData.name) {
+ console.warn('Invalid market stall data:', stallData)
+ return null
+ }
+
+ return {
+ id: stallData.id,
+ name: stallData.name,
+ description: stallData.description || '',
+ currency: stallData.currency || 'sat',
+ shipping: Array.isArray(stallData.shipping) ? stallData.shipping : []
+ }
+ } catch (error) {
+ console.error('Failed to parse market stall event:', error, event)
+ return null
+ }
+}
+
+/**
+ * Check if an event is a market-related event
+ */
+export function isMarketEvent(event: NostrEvent): boolean {
+ return event.kind === 30017 || event.kind === 30018 || event.kind === 30019
+}
+
+/**
+ * Get a human-readable type for a market event
+ */
+export function getMarketEventType(event: NostrEvent): string {
+ switch (event.kind) {
+ case 30017:
+ return 'Market Stall'
+ case 30018:
+ return 'Product'
+ case 30019:
+ return 'Market Activity'
+ default:
+ return 'Unknown Market Event'
+ }
+}
\ No newline at end of file