|
1 | 1 | import BitkitCore |
2 | 2 | import Foundation |
3 | 3 |
|
4 | | -// MARK: - Response Models |
5 | | - |
6 | | -private struct LnurlPayResponse: Codable { |
7 | | - let pr: String |
8 | | - let routes: [String] |
| 4 | +struct LnurlPayInvoiceMismatchError: LocalizedError { |
| 5 | + var errorDescription: String? { |
| 6 | + return "The invoice did not match the requested payment. Payment cancelled." |
| 7 | + } |
9 | 8 | } |
10 | 9 |
|
| 10 | +// MARK: - Response Models |
| 11 | + |
11 | 12 | private struct LnurlWithdrawResponse: Codable { |
12 | 13 | let status: String |
13 | 14 | let reason: String? |
@@ -116,37 +117,42 @@ private extension LnurlHelper { |
116 | 117 | throw NSError(domain: "LNURL", code: -1, userInfo: [NSLocalizedDescriptionKey: errorMessage]) |
117 | 118 | } |
118 | 119 | } |
| 120 | + |
| 121 | + static func mapLnurlPayInvoiceError(_ error: Error) -> Error { |
| 122 | + if let lnurlError = error as? LnurlError { |
| 123 | + switch lnurlError { |
| 124 | + case .InvalidAmount, .AmountMismatch, .MetadataMismatch: |
| 125 | + return LnurlPayInvoiceMismatchError() |
| 126 | + default: |
| 127 | + break |
| 128 | + } |
| 129 | + } |
| 130 | + |
| 131 | + return error |
| 132 | + } |
119 | 133 | } |
120 | 134 |
|
121 | 135 | @MainActor |
122 | 136 | struct LnurlHelper { |
123 | | - /// Fetches a Lightning invoice from an LNURL pay callback |
| 137 | + /// Fetches a Lightning invoice for an LNURL pay request |
124 | 138 | /// - Parameters: |
125 | | - /// - callbackUrl: The LNURL callback URL |
| 139 | + /// - data: The LNURL pay data |
126 | 140 | /// - amountMsats: The amount in millisatoshis to pay |
127 | 141 | /// - comment: Optional comment to include with the payment |
128 | 142 | /// - Returns: The bolt11 invoice string |
129 | 143 | /// - Throws: Network or parsing errors |
130 | 144 | static func fetchLnurlInvoice( |
131 | | - callbackUrl: String, |
| 145 | + data: LnurlPayData, |
132 | 146 | amountMsats: UInt64, |
133 | 147 | comment: String? = nil |
134 | 148 | ) async throws -> String { |
135 | | - var queryItems = [ |
136 | | - URLQueryItem(name: "amount", value: String(amountMsats)), |
137 | | - ] |
138 | | - |
139 | | - // Add comment if provided |
140 | | - if let comment, !comment.isEmpty { |
141 | | - queryItems.append(URLQueryItem(name: "comment", value: comment)) |
| 149 | + do { |
| 150 | + let invoice = try await getLnurlInvoiceForPayData(data: data, amountMsats: amountMsats, comment: comment) |
| 151 | + Logger.debug("Fetched LNURL pay invoice") |
| 152 | + return invoice |
| 153 | + } catch { |
| 154 | + throw mapLnurlPayInvoiceError(error) |
142 | 155 | } |
143 | | - |
144 | | - let callbackURL = try buildUrl(baseUrl: callbackUrl, queryItems: queryItems) |
145 | | - let responseString = try await makeHttpGetRequest(url: callbackURL) |
146 | | - let lnurlResponse = try parseJsonResponse(responseString, as: LnurlPayResponse.self) |
147 | | - |
148 | | - Logger.debug("Extracted bolt11 invoice: \(lnurlResponse.pr)") |
149 | | - return lnurlResponse.pr |
150 | 156 | } |
151 | 157 |
|
152 | 158 | /// Handles LNURL Withdraw Requests |
|
0 commit comments