Refactor market components for improved structure and functionality
- Update imports in DashboardOverview.vue to use relative paths for better module organization. - Modify OrderHistory.vue to replace 'lightningInvoice' with 'paymentRequest' for consistency in payment handling. - Enhance order event handling in useMarket.ts by adding subscription and decryption logic for order-related DMs. - Update nostrmarketService.ts to use relative imports, ensuring consistency across the module. - Introduce error handling and logging for order updates, improving the robustness of the market module.
This commit is contained in:
parent
36638d1080
commit
f5ea2a8d5e
4 changed files with 110 additions and 12 deletions
|
|
@ -215,11 +215,11 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { useMarketStore } from '@/stores/market'
|
import { useMarketStore } from '../stores/market'
|
||||||
import { useAuth } from '@/composables/useAuth'
|
import { useAuth } from '@/composables/useAuth'
|
||||||
import { useMarket } from '@/composables/useMarket'
|
import { useMarket } from '../composables/useMarket'
|
||||||
// import { useOrderEvents } from '@/composables/useOrderEvents' // TODO: Move to market module
|
// import { useOrderEvents } from '@/composables/useOrderEvents' // TODO: Move to market module
|
||||||
import { Button } from '@/components/ui/button'
|
import { Button } from '@/components/ui/button'
|
||||||
import { Badge } from '@/components/ui/badge'
|
import { Badge } from '@/components/ui/badge'
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Payment Section -->
|
<!-- Payment Section -->
|
||||||
<div v-if="order.lightningInvoice" class="mb-4 p-4 bg-muted/50 border border-border rounded-lg">
|
<div v-if="order.paymentRequest" class="mb-4 p-4 bg-muted/50 border border-border rounded-lg">
|
||||||
<div class="flex items-center justify-between mb-3">
|
<div class="flex items-center justify-between mb-3">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<Zap class="w-4 h-4 text-yellow-500" />
|
<Zap class="w-4 h-4 text-yellow-500" />
|
||||||
|
|
@ -127,9 +127,9 @@
|
||||||
Payment Request
|
Payment Request
|
||||||
</label>
|
</label>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<input :value="order.lightningInvoice?.bolt11 || ''" readonly disabled
|
<input :value="order.paymentRequest || ''" readonly disabled
|
||||||
class="flex-1 font-mono text-xs bg-muted border border-input rounded-md px-3 py-1 text-foreground" />
|
class="flex-1 font-mono text-xs bg-muted border border-input rounded-md px-3 py-1 text-foreground" />
|
||||||
<Button @click="copyPaymentRequest(order.lightningInvoice?.bolt11 || '')" variant="outline" size="sm">
|
<Button @click="copyPaymentRequest(order.paymentRequest || '')" variant="outline" size="sm">
|
||||||
<Copy class="w-3 h-3" />
|
<Copy class="w-3 h-3" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -137,8 +137,8 @@
|
||||||
|
|
||||||
<!-- Payment Actions -->
|
<!-- Payment Actions -->
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<Button @click="openLightningWallet(order.lightningInvoice?.bolt11 || '')" variant="default" size="sm"
|
<Button @click="openLightningWallet(order.paymentRequest || '')" variant="default" size="sm"
|
||||||
class="flex-1" :disabled="!order.lightningInvoice?.bolt11">
|
class="flex-1" :disabled="!order.paymentRequest">
|
||||||
<Zap class="w-3 h-3 mr-1" />
|
<Zap class="w-3 h-3 mr-1" />
|
||||||
Pay with Lightning
|
Pay with Lightning
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -244,7 +244,15 @@ const router = useRouter()
|
||||||
const marketStore = useMarketStore()
|
const marketStore = useMarketStore()
|
||||||
const relayHub = injectService(SERVICE_TOKENS.RELAY_HUB)
|
const relayHub = injectService(SERVICE_TOKENS.RELAY_HUB)
|
||||||
// const orderEvents = useOrderEvents() // TODO: Move to market module
|
// const orderEvents = useOrderEvents() // TODO: Move to market module
|
||||||
const orderEvents = { isSubscribed: ref(false), subscribeToOrderEvents: () => {}, cleanup: () => {} } // Temporary mock
|
const orderEvents = {
|
||||||
|
isSubscribed: ref(false),
|
||||||
|
subscribeToOrderEvents: () => {},
|
||||||
|
cleanup: () => {},
|
||||||
|
initialize: () => {
|
||||||
|
console.log('OrderEvents mock initialize called')
|
||||||
|
orderEvents.isSubscribed.value = true
|
||||||
|
}
|
||||||
|
} // Temporary mock
|
||||||
|
|
||||||
// Local state
|
// Local state
|
||||||
const statusFilter = ref('')
|
const statusFilter = ref('')
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ import { useNostrStore } from '@/stores/nostr'
|
||||||
import { useMarketStore } from '../stores/market'
|
import { useMarketStore } from '../stores/market'
|
||||||
import { injectService, SERVICE_TOKENS } from '@/core/di-container'
|
import { injectService, SERVICE_TOKENS } from '@/core/di-container'
|
||||||
import { config } from '@/lib/config'
|
import { config } from '@/lib/config'
|
||||||
|
import { nostrmarketService } from '../services/nostrmarketService'
|
||||||
|
import { nip04 } from 'nostr-tools'
|
||||||
|
|
||||||
// Nostr event kinds for market functionality
|
// Nostr event kinds for market functionality
|
||||||
const MARKET_EVENT_KINDS = {
|
const MARKET_EVENT_KINDS = {
|
||||||
|
|
@ -333,6 +335,89 @@ export function useMarket() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Subscribe to order-related DMs (payment requests, status updates)
|
||||||
|
const subscribeToOrderUpdates = (): (() => void) | null => {
|
||||||
|
try {
|
||||||
|
// TODO: Confirm if this should use nostrStore.account?.pubkey or authService.user.value?.pubkey
|
||||||
|
const userPubkey = nostrStore.account?.pubkey || authService.user.value?.pubkey
|
||||||
|
if (!userPubkey) {
|
||||||
|
console.warn('Cannot subscribe to order updates: no user pubkey available', {
|
||||||
|
nostrStorePubkey: nostrStore.account?.pubkey,
|
||||||
|
authServicePubkey: authService.user.value?.pubkey,
|
||||||
|
isAuthenticated: authService.isAuthenticated.value
|
||||||
|
})
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('🔔 Setting up order updates subscription for user:', userPubkey.slice(0, 8))
|
||||||
|
|
||||||
|
// Subscribe to encrypted DMs directed to this user (payment requests, status updates)
|
||||||
|
const unsubscribe = relayHub.subscribe({
|
||||||
|
id: `order-updates-${userPubkey}`,
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
kinds: [4], // Encrypted DMs
|
||||||
|
'#p': [userPubkey], // Messages directed to this user
|
||||||
|
since: Math.floor(Date.now() / 1000) - 3600 // Last hour to avoid old messages
|
||||||
|
}
|
||||||
|
],
|
||||||
|
onEvent: async (event: any) => {
|
||||||
|
await handleOrderDM(event)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return unsubscribe
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to subscribe to order updates:', error)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle incoming order DMs (payment requests, status updates)
|
||||||
|
const handleOrderDM = async (event: any) => {
|
||||||
|
try {
|
||||||
|
console.log('🔔 Received order-related DM:', event.id, 'from:', event.pubkey.slice(0, 8))
|
||||||
|
|
||||||
|
// TODO: Confirm if this should use nostrStore.account?.pubkey or authService.user.value?.pubkey
|
||||||
|
const userPubkey = nostrStore.account?.pubkey || authService.user.value?.pubkey
|
||||||
|
const userPrivkey = nostrStore.account?.privkey || authService.user.value?.prvkey
|
||||||
|
|
||||||
|
if (!userPrivkey) {
|
||||||
|
console.warn('Cannot decrypt DM: no user private key available', {
|
||||||
|
nostrStorePrivkey: !!nostrStore.account?.privkey,
|
||||||
|
authServicePrivkey: !!authService.user.value?.prvkey
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('🔓 Attempting to decrypt DM with private key available')
|
||||||
|
|
||||||
|
// Decrypt the DM content
|
||||||
|
const decryptedContent = await nip04.decrypt(userPrivkey, event.pubkey, event.content)
|
||||||
|
console.log('🔓 Decrypted DM content:', decryptedContent)
|
||||||
|
|
||||||
|
// Parse the decrypted content as JSON
|
||||||
|
const messageData = JSON.parse(decryptedContent)
|
||||||
|
console.log('📨 Parsed message data:', messageData)
|
||||||
|
|
||||||
|
// Handle different types of messages
|
||||||
|
switch (messageData.type) {
|
||||||
|
case 1: // Payment request
|
||||||
|
console.log('💰 Processing payment request')
|
||||||
|
await nostrmarketService.handlePaymentRequest(messageData)
|
||||||
|
break
|
||||||
|
case 2: // Order status update
|
||||||
|
console.log('📦 Processing order status update')
|
||||||
|
await nostrmarketService.handleOrderStatusUpdate(messageData)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
console.log('❓ Unknown message type:', messageData.type)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to handle order DM:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Handle incoming market events
|
// Handle incoming market events
|
||||||
const handleMarketEvent = (event: any) => {
|
const handleMarketEvent = (event: any) => {
|
||||||
// Process market event
|
// Process market event
|
||||||
|
|
@ -494,6 +579,10 @@ export function useMarket() {
|
||||||
// Subscribe to updates
|
// Subscribe to updates
|
||||||
console.log('🛒 Subscribing to market updates...')
|
console.log('🛒 Subscribing to market updates...')
|
||||||
subscribeToMarketUpdates()
|
subscribeToMarketUpdates()
|
||||||
|
|
||||||
|
// Subscribe to order-related DMs
|
||||||
|
console.log('🛒 Subscribing to order updates...')
|
||||||
|
subscribeToOrderUpdates()
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('🛒 Failed to connect to market:', err)
|
console.error('🛒 Failed to connect to market:', err)
|
||||||
|
|
@ -540,6 +629,7 @@ export function useMarket() {
|
||||||
processPendingProducts,
|
processPendingProducts,
|
||||||
publishProduct,
|
publishProduct,
|
||||||
publishStall,
|
publishStall,
|
||||||
subscribeToMarketUpdates
|
subscribeToMarketUpdates,
|
||||||
|
subscribeToOrderUpdates
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -330,7 +330,7 @@ export class NostrmarketService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the order in the store with payment request
|
// Update the order in the store with payment request
|
||||||
const { useMarketStore } = await import('@/stores/market')
|
const { useMarketStore } = await import('../stores/market')
|
||||||
const marketStore = useMarketStore()
|
const marketStore = useMarketStore()
|
||||||
|
|
||||||
const order = Object.values(marketStore.orders).find(o =>
|
const order = Object.values(marketStore.orders).find(o =>
|
||||||
|
|
@ -393,7 +393,7 @@ export class NostrmarketService {
|
||||||
shipped: statusUpdate.shipped
|
shipped: statusUpdate.shipped
|
||||||
})
|
})
|
||||||
|
|
||||||
const { useMarketStore } = await import('@/stores/market')
|
const { useMarketStore } = await import('../stores/market')
|
||||||
const marketStore = useMarketStore()
|
const marketStore = useMarketStore()
|
||||||
|
|
||||||
const order = Object.values(marketStore.orders).find(o =>
|
const order = Object.values(marketStore.orders).find(o =>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue