Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions Bitkit/Utilities/PaymentNavigationHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ struct PaymentNavigationHelper {
app: AppViewModel,
currency: CurrencyViewModel,
settings: SettingsViewModel
) -> SendRoute {
) -> SendRoute? {
if let lnurlWithdrawData = app.lnurlWithdrawData {
if lnurlWithdrawData.minWithdrawable == lnurlWithdrawData.maxWithdrawable {
return .lnurlWithdrawConfirm
Expand All @@ -125,8 +125,8 @@ struct PaymentNavigationHelper {
}

// Handle lightning invoice
if app.scannedLightningInvoice != nil {
let amount = app.scannedLightningInvoice!.amountSatoshis
if let invoice = app.scannedLightningInvoice {
let amount = invoice.amountSatoshis

if amount > 0 && shouldUseQuickpay {
return .quickpay
Expand All @@ -140,6 +140,11 @@ struct PaymentNavigationHelper {
}

// Handle onchain invoice
return .amount
if let _ = app.scannedOnchainInvoice {
return .amount
}

// No valid invoice data
return nil
}
}
22 changes: 16 additions & 6 deletions Bitkit/ViewModels/AppViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -177,27 +177,37 @@ extension AppViewModel {
}
// Lightning invoice param found, prefer lightning payment if possible
if case let .lightning(lightningInvoice) = try await decode(invoice: lnInvoice) {
if lightningService.canSend(amountSats: lightningInvoice.amountSatoshis) {
if !lightningInvoice.isExpired, lightningService.canSend(amountSats: lightningInvoice.amountSatoshis) {
handleScannedLightningInvoice(lightningInvoice, bolt11: lnInvoice, onchainInvoice: invoice)
return
}
// Lightning not usable (expired or insufficient funds) - fallback to on-chain if available
if lightningInvoice.isExpired {
toast(type: .error, title: t("other__scan__error__expired"), description: nil)
}
}
}

// No LN invoice found, proceed with onchain payment
// Fallback to on-chain if address is available
guard !invoice.address.isEmpty else { return }
handleScannedOnchainInvoice(invoice)
case let .lightning(invoice):
guard lightningService.status?.isRunning == true else {
toast(type: .error, title: "Lightning not running", description: "Please try again later.")
return
}

Logger.debug("Lightning: \(invoice)")
if lightningService.canSend(amountSats: invoice.amountSatoshis) {
handleScannedLightningInvoice(invoice, bolt11: uri)
} else {
guard !invoice.isExpired else {
toast(type: .error, title: t("other__scan__error__expired"), description: nil)
return
}

guard lightningService.canSend(amountSats: invoice.amountSatoshis) else {
toast(type: .error, title: "Insufficient Funds", description: "You do not have enough funds to send this payment.")
return
}

handleScannedLightningInvoice(invoice, bolt11: uri)
case let .lnurlPay(data: lnurlPayData):
Logger.debug("LNURL: \(lnurlPayData)")
handleLnurlPayInvoice(lnurlPayData)
Expand Down
5 changes: 5 additions & 0 deletions Bitkit/Views/Wallets/Send/SendConfirmationView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,11 @@ struct SendConfirmationView: View {
var createdMetadataPaymentId: String? = nil

do {
if app.selectedWalletToPayFrom == .lightning, let invoice = app.scannedLightningInvoice, invoice.isExpired {
app.toast(type: .error, title: t("other__scan__error__expired"), description: nil)
return
}

if app.selectedWalletToPayFrom == .lightning, let invoice = app.scannedLightningInvoice {
let amount = wallet.sendAmountSats ?? invoice.amountSatoshis
// Set the amount for the success screen
Expand Down
7 changes: 4 additions & 3 deletions Bitkit/Views/Wallets/Send/SendEnterManuallyView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,13 @@ struct SendEnterManuallyView: View {
do {
try await app.handleScannedData(uri)

let route = PaymentNavigationHelper.appropriateSendRoute(
if let route = PaymentNavigationHelper.appropriateSendRoute(
app: app,
currency: currency,
settings: settings
)
navigationPath.append(route)
) {
navigationPath.append(route)
}
} catch {
Logger.error(error, context: "Failed to read data from clipboard")
app.toast(error)
Expand Down
Loading