Skip to content

Commit 83c9018

Browse files
authored
Merge pull request synonymdev#320 from synonymdev/fix/fallback-expired-ln-to-onchain
fix: fallback expired Bolt 11 to on-chain on unified invoice
2 parents 9d2ac61 + 93b04c7 commit 83c9018

10 files changed

Lines changed: 517 additions & 20 deletions

File tree

Bitkit/Resources/Localization/en.lproj/Localizable.strings

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@
370370
"other__pay_insufficient_spending" = "Insufficient Spending Balance";
371371
"other__pay_insufficient_savings_description" = "More ₿ needed to pay this Bitcoin invoice.";
372372
"other__pay_insufficient_savings_amount_description" = "₿ {amount} more needed to pay this Bitcoin invoice.";
373+
"other__pay_insufficient_spending_description" = "More ₿ needed to pay this Lightning invoice.";
373374
"other__pay_insufficient_spending_amount_description" = "₿ {amount} more needed to pay this Lightning invoice.";
374375
"other__swipe" = "Swipe To Confirm";
375376
"other__scan_err_decoding" = "Decoding Error";

Bitkit/Utilities/Bip21Utils.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import Foundation
2+
3+
/// Utility methods for BIP21 URI handling
4+
enum Bip21Utils {
5+
private static let bip21Prefix = "bitcoin:"
6+
7+
/// Checks if a BIP21 URI is duplicated (contains multiple bitcoin: prefixes).
8+
/// Workaround for https://github.com/synonymdev/bitkit-core/issues/63
9+
/// - Parameter input: The string to check
10+
/// - Returns: true if the input contains duplicated BIP21 URIs, false otherwise
11+
static func isDuplicatedBip21(_ input: String) -> Bool {
12+
let lowercased = input.lowercased()
13+
guard let firstIndex = lowercased.range(of: bip21Prefix)?.upperBound else {
14+
return false
15+
}
16+
return lowercased[firstIndex...].contains(bip21Prefix)
17+
}
18+
}

Bitkit/Utilities/CurrencyFormatter.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,12 @@ enum CurrencyFormatter {
99

1010
return formatter.string(from: amount as NSDecimalNumber) ?? ""
1111
}
12+
13+
/// Format satoshis with space as grouping separator (e.g., 10000 -> "10 000")
14+
static func formatSats(_ sats: UInt64) -> String {
15+
let formatter = NumberFormatter()
16+
formatter.numberStyle = .decimal
17+
formatter.groupingSeparator = " "
18+
return formatter.string(from: NSNumber(value: sats)) ?? String(sats)
19+
}
1220
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import BitkitCore
2+
import LDKNode
3+
4+
/// Helper for validating Bitcoin network compatibility of addresses and invoices
5+
enum NetworkValidationHelper {
6+
/// Convert BitkitCore.NetworkType to LDKNode.Network
7+
/// - Parameter networkType: The BitkitCore network type
8+
/// - Returns: The equivalent LDKNode network
9+
static func convertNetworkType(_ networkType: NetworkType) -> LDKNode.Network {
10+
switch networkType {
11+
case .bitcoin: return .bitcoin
12+
case .testnet: return .testnet
13+
case .signet: return .signet
14+
case .regtest: return .regtest
15+
}
16+
}
17+
18+
/// Check if an address/invoice network mismatches the current app network
19+
/// - Parameters:
20+
/// - addressNetwork: The network detected from the address/invoice
21+
/// - currentNetwork: The app's current network (typically Env.network)
22+
/// - Returns: true if there's a mismatch (address won't work on current network)
23+
static func isNetworkMismatch(addressNetwork: LDKNode.Network?, currentNetwork: LDKNode.Network) -> Bool {
24+
guard let addressNetwork else { return false }
25+
26+
// Special case: regtest uses testnet prefixes (m, n, 2, tb1)
27+
if currentNetwork == .regtest && addressNetwork == .testnet {
28+
return false
29+
}
30+
31+
return addressNetwork != currentNetwork
32+
}
33+
}

Bitkit/Utilities/PaymentNavigationHelper.swift

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ struct PaymentNavigationHelper {
102102
app: AppViewModel,
103103
currency: CurrencyViewModel,
104104
settings: SettingsViewModel
105-
) -> SendRoute {
105+
) -> SendRoute? {
106106
if let lnurlWithdrawData = app.lnurlWithdrawData {
107107
if lnurlWithdrawData.minWithdrawable == lnurlWithdrawData.maxWithdrawable {
108108
return .lnurlWithdrawConfirm
@@ -125,8 +125,8 @@ struct PaymentNavigationHelper {
125125
}
126126

127127
// Handle lightning invoice
128-
if app.scannedLightningInvoice != nil {
129-
let amount = app.scannedLightningInvoice!.amountSatoshis
128+
if let invoice = app.scannedLightningInvoice {
129+
let amount = invoice.amountSatoshis
130130

131131
if amount > 0 && shouldUseQuickpay {
132132
return .quickpay
@@ -140,6 +140,11 @@ struct PaymentNavigationHelper {
140140
}
141141

142142
// Handle onchain invoice
143-
return .amount
143+
if let _ = app.scannedOnchainInvoice {
144+
return .amount
145+
}
146+
147+
// No valid invoice data
148+
return nil
144149
}
145150
}

0 commit comments

Comments
 (0)