Refactor ReceiveDialog.vue for Lightning invoice creation
- Updated the form to create Lightning invoices instead of LNURL addresses, changing the validation schema and input fields accordingly. - Introduced new state management for created invoices and adjusted the submission logic to handle invoice creation. - Enhanced the UI to display invoice details, including amount, memo, and QR code generation for the invoice. - Removed unused components and streamlined the dialog's functionality for a more focused user experience. These changes improve the functionality and user interface of the ReceiveDialog component, facilitating easier invoice management for Bitcoin payments.
This commit is contained in:
parent
27070c0390
commit
21e1c8f7c0
3 changed files with 280 additions and 318 deletions
|
|
@ -21,6 +21,23 @@ export interface SendPaymentRequest {
|
|||
comment?: string
|
||||
}
|
||||
|
||||
export interface CreateInvoiceRequest {
|
||||
amount: number
|
||||
memo: string
|
||||
expiry?: number // Optional expiry in seconds
|
||||
}
|
||||
|
||||
export interface Invoice {
|
||||
payment_hash: string
|
||||
bolt11: string // The BOLT11 invoice
|
||||
payment_request: string // Same as bolt11, for compatibility
|
||||
checking_id: string
|
||||
amount: number
|
||||
memo: string
|
||||
time: number
|
||||
expiry: number | null
|
||||
}
|
||||
|
||||
export interface PaymentTransaction {
|
||||
id: string
|
||||
amount: number
|
||||
|
|
@ -47,6 +64,7 @@ export default class WalletService extends BaseService {
|
|||
private _transactions = ref<PaymentTransaction[]>([])
|
||||
private _isCreatingPayLink = ref(false)
|
||||
private _isSendingPayment = ref(false)
|
||||
private _isCreatingInvoice = ref(false)
|
||||
private _error = ref<string | null>(null)
|
||||
|
||||
// Public reactive getters
|
||||
|
|
@ -54,6 +72,7 @@ export default class WalletService extends BaseService {
|
|||
readonly transactions = computed(() => this._transactions.value)
|
||||
readonly isCreatingPayLink = computed(() => this._isCreatingPayLink.value)
|
||||
readonly isSendingPayment = computed(() => this._isSendingPayment.value)
|
||||
readonly isCreatingInvoice = computed(() => this._isCreatingInvoice.value)
|
||||
readonly error = computed(() => this._error.value)
|
||||
|
||||
protected async onInitialize(): Promise<void> {
|
||||
|
|
@ -148,6 +167,63 @@ export default class WalletService extends BaseService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Lightning invoice for receiving payments
|
||||
*/
|
||||
async createInvoice(request: CreateInvoiceRequest): Promise<Invoice | null> {
|
||||
this._isCreatingInvoice.value = true
|
||||
this._error.value = null
|
||||
|
||||
try {
|
||||
const invoiceKey = this.paymentService?.getPreferredWalletInvoiceKey()
|
||||
if (!invoiceKey) {
|
||||
throw new Error('No invoice key available')
|
||||
}
|
||||
|
||||
// Create invoice via LNbits payments API
|
||||
const response = await fetch(`${config.api.baseUrl}/api/v1/payments`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Api-Key': invoiceKey
|
||||
},
|
||||
body: JSON.stringify({
|
||||
out: false, // Incoming payment (receiving)
|
||||
amount: request.amount,
|
||||
unit: 'sat',
|
||||
memo: request.memo,
|
||||
expiry: request.expiry || 3600 // Default 1 hour expiry
|
||||
})
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const error = await response.json()
|
||||
throw new Error(error.detail || 'Failed to create invoice')
|
||||
}
|
||||
|
||||
const rawInvoice = await response.json()
|
||||
console.log('Raw invoice response:', rawInvoice)
|
||||
|
||||
// Process the response to fix data issues
|
||||
const invoice: Invoice = {
|
||||
...rawInvoice,
|
||||
payment_request: rawInvoice.bolt11, // Copy bolt11 to payment_request for compatibility
|
||||
amount: rawInvoice.amount / 1000, // Convert from millisats to sats
|
||||
expiry: rawInvoice.expiry ? this.parseExpiryToSeconds(rawInvoice.expiry) : null
|
||||
}
|
||||
|
||||
console.log('Processed invoice:', invoice)
|
||||
return invoice
|
||||
|
||||
} catch (error) {
|
||||
console.error('Failed to create invoice:', error)
|
||||
this._error.value = error instanceof Error ? error.message : 'Failed to create invoice'
|
||||
return null
|
||||
} finally {
|
||||
this._isCreatingInvoice.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a Lightning payment
|
||||
*/
|
||||
|
|
@ -351,6 +427,21 @@ export default class WalletService extends BaseService {
|
|||
])
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse expiry date string to seconds from now
|
||||
*/
|
||||
private parseExpiryToSeconds(expiryStr: string): number {
|
||||
try {
|
||||
const expiryDate = new Date(expiryStr)
|
||||
const now = new Date()
|
||||
const diffMs = expiryDate.getTime() - now.getTime()
|
||||
return Math.max(0, Math.floor(diffMs / 1000)) // Return seconds, minimum 0
|
||||
} catch (error) {
|
||||
console.error('Failed to parse expiry date:', expiryStr, error)
|
||||
return 3600 // Default to 1 hour
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new transaction from WebSocket notification
|
||||
*/
|
||||
|
|
@ -390,4 +481,4 @@ export default class WalletService extends BaseService {
|
|||
tag: payment.tag || null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue