Implement Lightning payment handling in OrderHistory component

- Replace the existing openLightningWallet function with payWithLightning for improved payment processing.
- Introduce useLightningPayment composable to manage wallet payment logic and state.
- Update button text dynamically based on payment status and wallet availability.
- Enhance error handling and user feedback during payment attempts, ensuring a smoother user experience.
This commit is contained in:
padreug 2025-09-05 04:50:35 +02:00
parent f5ea2a8d5e
commit db9b50240d
2 changed files with 171 additions and 26 deletions

View file

@ -0,0 +1,159 @@
import { ref, computed } from 'vue'
import { useAuth } from '@/composables/useAuth'
import { useMarketStore } from '../stores/market'
import { payInvoiceWithWallet } from '@/lib/api/events'
import { toast } from 'vue-sonner'
export function useLightningPayment() {
const { isAuthenticated, currentUser } = useAuth()
const marketStore = useMarketStore()
// State
const isPayingWithWallet = ref(false)
const paymentError = ref<string | null>(null)
// Computed properties
const userWallets = computed(() => currentUser.value?.wallets || [])
const hasWalletWithBalance = computed(() =>
userWallets.value.some((wallet: any) => wallet.balance_msat > 0)
)
// Get wallet with sufficient balance
const getWalletWithBalance = (requiredAmount?: number) => {
const wallets = userWallets.value
if (!wallets.length) return null
if (requiredAmount) {
return wallets.find((wallet: any) => wallet.balance_msat >= requiredAmount * 1000) // Convert sats to msat
}
return wallets.find((wallet: any) => wallet.balance_msat > 0)
}
// Pay Lightning invoice with user's wallet
async function payInvoice(paymentRequest: string, orderId?: string): Promise<boolean> {
if (!isAuthenticated.value || !currentUser.value) {
throw new Error('User must be authenticated to pay with wallet')
}
const wallet = getWalletWithBalance()
if (!wallet) {
throw new Error('No wallet with sufficient balance found')
}
try {
isPayingWithWallet.value = true
paymentError.value = null
console.log('💰 Paying invoice with wallet:', wallet.id.slice(0, 8))
// Use the same API function as events
const paymentResult = await payInvoiceWithWallet(paymentRequest, wallet.id, wallet.adminkey)
console.log('✅ Payment successful:', {
paymentHash: paymentResult.payment_hash,
feeMsat: paymentResult.fee_msat,
orderId
})
// Update order status to paid if orderId is provided
if (orderId) {
const order = marketStore.orders[orderId]
if (order) {
const updatedOrder = {
...order,
paymentStatus: 'paid' as const,
status: 'paid' as const,
paidAt: Math.floor(Date.now() / 1000),
paymentHash: paymentResult.payment_hash,
feeMsat: paymentResult.fee_msat,
items: [...order.items] // Convert readonly to mutable
}
marketStore.updateOrder(orderId, updatedOrder)
}
}
toast.success('Payment successful!', {
description: orderId ? `Order ${orderId.slice(-8)} has been paid` : 'Lightning invoice paid successfully'
})
return true
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Payment failed'
paymentError.value = errorMessage
console.error('💸 Payment failed:', error)
toast.error('Payment failed', {
description: errorMessage
})
throw error
} finally {
isPayingWithWallet.value = false
}
}
// Open external Lightning wallet (fallback)
function openExternalLightningWallet(paymentRequest: string) {
if (!paymentRequest) {
toast.error('No payment request available')
return
}
// Try lightning: protocol first
const lightningUrl = `lightning:${paymentRequest}`
try {
window.open(lightningUrl, '_blank')
toast.info('Opening Lightning wallet...', {
description: 'If no wallet opens, copy the payment request manually'
})
} catch (error) {
console.warn('Failed to open lightning: URL, showing payment request for copy:', error)
// Fallback: copy to clipboard or show for manual copy
navigator.clipboard?.writeText(paymentRequest).then(() => {
toast.success('Payment request copied to clipboard')
}).catch(() => {
toast.info('Please copy the payment request manually')
})
}
}
// Main payment handler - tries wallet first, falls back to external
async function handlePayment(paymentRequest: string, orderId?: string): Promise<void> {
if (!paymentRequest) {
toast.error('No payment request available')
return
}
// Try wallet payment first if user has balance
if (hasWalletWithBalance.value) {
try {
await payInvoice(paymentRequest, orderId)
return // Payment successful with wallet
} catch (error) {
console.log('Wallet payment failed, offering external wallet option:', error)
// Don't throw here, continue to external wallet option
}
}
// Fallback to external wallet
openExternalLightningWallet(paymentRequest)
}
return {
// State
isPayingWithWallet,
paymentError,
// Computed
hasWalletWithBalance,
userWallets,
// Methods
payInvoice,
openExternalLightningWallet,
handlePayment,
getWalletWithBalance
}
}