taler-ios

iOS apps for GNU Taler (wallet)
Log | Files | Refs | README | LICENSE

commit e6fc4a6c1383e0cd52d9c13df9e04cc5f14cb279
parent cf4e4fc16e614126c1a77ce2ffd9f8200dbcd485
Author: Marc Stibane <marc@taler.net>
Date:   Sun, 25 Jun 2023 09:58:43 +0200

Sounds, P2P receive

Diffstat:
MTalerWallet.xcodeproj/project.pbxproj | 10+++++++++-
MTalerWallet1/Backend/Transaction.swift | 30+++++++++++++++++-------------
MTalerWallet1/Backend/WalletCore.swift | 2+-
ATalerWallet1/Helper/playSound.swift | 12++++++++++++
MTalerWallet1/Model/Model+P2P.swift | 39+++++++++++++++++++++++++++++----------
MTalerWallet1/Model/Model+Withdraw.swift | 1-
MTalerWallet1/Views/HelperViews/QRCodeDetailView.swift | 4++--
MTalerWallet1/Views/Payment/PaymentURIView.swift | 11+++--------
MTalerWallet1/Views/Peer2peer/SendNow.swift | 24++++++++++++------------
MTalerWallet1/Views/Sheets/P2P_Sheets/P2pAcceptDone.swift | 42++++++++++++++++++++----------------------
ATalerWallet1/Views/Sheets/P2P_Sheets/P2pPayURIView.swift | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MTalerWallet1/Views/Sheets/P2P_Sheets/P2pReceiveURIView.swift | 2+-
12 files changed, 191 insertions(+), 71 deletions(-)

diff --git a/TalerWallet.xcodeproj/project.pbxproj b/TalerWallet.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 52; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -20,6 +20,8 @@ 4E40E0BE29F25ABB00B85369 /* SendAmount.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E40E0BD29F25ABB00B85369 /* SendAmount.swift */; }; 4E50B3502A1BEE8000F9F01C /* ManualWithdraw.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E50B34F2A1BEE8000F9F01C /* ManualWithdraw.swift */; }; 4E53A33729F50B7B00830EC2 /* CurrencyField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E53A33629F50B7B00830EC2 /* CurrencyField.swift */; }; + 4E578E922A481D8600F21F1C /* playSound.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E578E912A481D8600F21F1C /* playSound.swift */; }; + 4E578E942A4822D500F21F1C /* P2pPayURIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E578E932A4822D500F21F1C /* P2pPayURIView.swift */; }; 4E5A88F52A38A4FD00072618 /* QRCodeDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E5A88F42A38A4FD00072618 /* QRCodeDetailView.swift */; }; 4E5A88F72A3B9E5B00072618 /* WithdrawAcceptDone.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E5A88F62A3B9E5B00072618 /* WithdrawAcceptDone.swift */; }; 4E6EDD852A3615BE0031D520 /* ManualDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E6EDD842A3615BE0031D520 /* ManualDetails.swift */; }; @@ -150,6 +152,8 @@ 4E40E0BD29F25ABB00B85369 /* SendAmount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SendAmount.swift; path = TalerWallet1/Views/Peer2peer/SendAmount.swift; sourceTree = SOURCE_ROOT; }; 4E50B34F2A1BEE8000F9F01C /* ManualWithdraw.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManualWithdraw.swift; sourceTree = "<group>"; }; 4E53A33629F50B7B00830EC2 /* CurrencyField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CurrencyField.swift; sourceTree = "<group>"; }; + 4E578E912A481D8600F21F1C /* playSound.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = playSound.swift; sourceTree = "<group>"; }; + 4E578E932A4822D500F21F1C /* P2pPayURIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = P2pPayURIView.swift; sourceTree = "<group>"; }; 4E5A88F42A38A4FD00072618 /* QRCodeDetailView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QRCodeDetailView.swift; sourceTree = "<group>"; }; 4E5A88F62A3B9E5B00072618 /* WithdrawAcceptDone.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WithdrawAcceptDone.swift; sourceTree = "<group>"; }; 4E6EDD842A3615BE0031D520 /* ManualDetails.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManualDetails.swift; sourceTree = "<group>"; }; @@ -272,6 +276,7 @@ isa = PBXGroup; children = ( 4E3B4BC02A41E6C200CC88B8 /* P2pReceiveURIView.swift */, + 4E578E932A4822D500F21F1C /* P2pPayURIView.swift */, 4E3B4BC22A42252300CC88B8 /* P2pAcceptDone.swift */, ); path = P2P_Sheets; @@ -329,6 +334,7 @@ 4E16E12229F3BB99008B9C86 /* CurrencyFormatter.swift */, 4EAD117529F672FA008EDD0B /* KeyboardResponder.swift */, 4E363CC12A2621C200D7E98C /* LocalizedAlertError.swift */, + 4E578E912A481D8600F21F1C /* playSound.swift */, 4EB095062989CB7C0043A8A1 /* TalerDater.swift */, 4EB095072989CB7C0043A8A1 /* TalerStrings.swift */, 4EB095082989CB7C0043A8A1 /* View+dismissTop.swift */, @@ -735,6 +741,7 @@ 4E87C8752A34B411001C6406 /* UncompletedRowView.swift in Sources */, 4E40E0BE29F25ABB00B85369 /* SendAmount.swift in Sources */, 4E8E25332A1CD39700A27BFA /* EqualIconWidthDomain.swift in Sources */, + 4E578E942A4822D500F21F1C /* P2pPayURIView.swift in Sources */, 4EB095542989CBFE0043A8A1 /* Model+Payment.swift in Sources */, 4EB0954F2989CBFE0043A8A1 /* SettingsView.swift in Sources */, 4EB095552989CBFE0043A8A1 /* PaymentURIView.swift in Sources */, @@ -760,6 +767,7 @@ 4E3B4BC32A42252300CC88B8 /* P2pAcceptDone.swift in Sources */, 4E363CBE2A23CB2100D7E98C /* AnyTransition+backslide.swift in Sources */, 4EB095592989CBFE0043A8A1 /* Model+Transactions.swift in Sources */, + 4E578E922A481D8600F21F1C /* playSound.swift in Sources */, 4EB0955F2989CBFE0043A8A1 /* WalletEmptyView.swift in Sources */, 4E16E12329F3BB99008B9C86 /* CurrencyFormatter.swift in Sources */, 4EB095092989CB7C0043A8A1 /* TalerDater.swift in Sources */, diff --git a/TalerWallet1/Backend/Transaction.swift b/TalerWallet1/Backend/Transaction.swift @@ -118,6 +118,22 @@ struct TransactionCommon: Decodable { var timestamp: Timestamp var txActions: [TxAction] + func localizedType(_ type: TransactionType) -> String { + switch type { + case .dummy: return String("") + case .withdrawal: return String(localized: "Withdrawal") + case .deposit: return String(localized: "Deposit") + case .payment: return String(localized: "Payment") + case .refund: return String(localized: "Refund") + case .refresh: return String(localized: "Refresh") + case .reward: return String(localized: "Reward") + case .peerPushDebit: return String(localized: "P2P Send", comment: "send coins to another wallet") + case .scanPushCredit: return String(localized: "P2P Receive", comment: "scan to receive coins sent from another wallet") + case .peerPullCredit: return String(localized: "P2P Invoice", comment: "send invoice to another wallet") + case .scanPullDebit: return String(localized: "P2P Payment", comment: "scan invoice to pay to another wallet") + } + } + func fee() -> Amount { do { return try Amount.diff(amountRaw, amountEffective) @@ -327,19 +343,7 @@ enum Transaction: Decodable, Hashable, Identifiable { var id: String { common.transactionId } var localizedType: String { - switch common.type { - case .dummy: return String("Dummy") - case .withdrawal: return String(localized: "Withdrawal") - case .deposit: return String(localized: "Deposit") - case .payment: return String(localized: "Payment") - case .refund: return String(localized: "Refund") - case .refresh: return String(localized: "Refresh") - case .reward: return String(localized: "Reward") - case .peerPushDebit: return String(localized: "P2P Send", comment: "send coins to another wallet") - case .scanPushCredit: return String(localized: "P2P Receive", comment: "scan to receive coins sent from another wallet") - case .peerPullCredit: return String(localized: "P2P Invoice", comment: "send invoice to another wallet") - case .scanPullDebit: return String(localized: "P2P Payment", comment: "scan invoice to pay to another wallet") - } + common.localizedType(common.type) } static func == (lhs: Transaction, rhs: Transaction) -> Bool { diff --git a/TalerWallet1/Backend/WalletCore.swift b/TalerWallet1/Backend/WalletCore.swift @@ -297,7 +297,7 @@ print("\n❗️ WalletCore.swift:226 Notification: ", anyPayload, "\n") / let now = Date.now do { let full = FullRequest(operation: request.operation, id: requestId, args: request.args) - // symLog.log(full) +// symLog.log(full) let encoded = try JSONEncoder().encode(full) guard let jsonString = String(data: encoded, encoding: .utf8) else { throw WalletBackendError.serializationError } self.completions[requestId] = (now, completionHandler) diff --git a/TalerWallet1/Helper/playSound.swift b/TalerWallet1/Helper/playSound.swift @@ -0,0 +1,12 @@ +/* + * This file is part of GNU Taler, ©2022-23 Taler Systems S.A. + * See LICENSE.md + */ +import Foundation +import AVFoundation + +func playSound(fileURL: URL) { + var soundID: SystemSoundID = 0 + AudioServicesCreateSystemSoundID(fileURL as CFURL, &soundID) + AudioServicesPlaySystemSound(soundID); +} diff --git a/TalerWallet1/Model/Model+P2P.swift b/TalerWallet1/Model/Model+P2P.swift @@ -59,7 +59,7 @@ fileprivate struct CheckPeerPullCredit: WalletBackendFormattedRequest { } // MARK: - /// The result from InitiatePeerPushDebit -struct PeerPushResponse: Codable { +struct InitiatePeerPushDebitResponse: Codable { let contractPriv: String let mergePriv: String let pursePub: String @@ -69,7 +69,7 @@ struct PeerPushResponse: Codable { } /// A request to send coins to another wallet. fileprivate struct InitiatePeerPushDebit: WalletBackendFormattedRequest { - typealias Response = PeerPushResponse + typealias Response = InitiatePeerPushDebitResponse func operation() -> String { return "initiatePeerPushDebit" } func args() -> Args { return Args(exchangeBaseUrl: exchangeBaseUrl, partialContractTerms: partialContractTerms) } @@ -81,12 +81,12 @@ fileprivate struct InitiatePeerPushDebit: WalletBackendFormattedRequest { var partialContractTerms: PeerContractTerms } } - +// MARK: - struct PreparePeerPushCreditResponse: Codable { let contractTerms: PeerContractTerms let amountRaw: Amount let amountEffective: Amount - let peerPushPaymentIncomingId: String + let transactionId: String // after scanning the transaction already is created in the local DB } /// A request to receive coins from another wallet. fileprivate struct PreparePeerPushCredit: WalletBackendFormattedRequest { @@ -100,14 +100,25 @@ fileprivate struct PreparePeerPushCredit: WalletBackendFormattedRequest { } } // MARK: - +fileprivate struct ConfirmPeerPushCredit: WalletBackendFormattedRequest { + struct Response: Decodable {} + func operation() -> String { return "confirmPeerPushCredit" } + func args() -> Args { return Args(transactionId: transactionId) } + + var transactionId: String + struct Args: Encodable { + var transactionId: String + } +} +// MARK: - /// The result from InitiatePeerPullCredit -struct PeerPullResponse: Codable { +struct InitiatePeerPullCreditResponse: Codable { let talerUri: String let transactionId: String } /// A request to send a payment request to another wallet. fileprivate struct InitiatePeerPullCredit: WalletBackendFormattedRequest { - typealias Response = PeerPullResponse + typealias Response = InitiatePeerPullCreditResponse func operation() -> String { return "initiatePeerPullCredit" } func args() -> Args { return Args(exchangeBaseUrl: exchangeBaseUrl, partialContractTerms: partialContractTerms) } @@ -132,7 +143,7 @@ extension WalletModel { /// generate peer-push. Networking involved @MainActor func initiatePeerPushDebitM(_ baseURL: String?, terms: PeerContractTerms) // M for MainActor - async throws -> PeerPushResponse { + async throws -> InitiatePeerPushDebitResponse { let request = InitiatePeerPushDebit(exchangeBaseUrl: baseURL, partialContractTerms: terms) let response = try await sendRequest(request, ASYNCDELAY) @@ -142,7 +153,7 @@ extension WalletModel { /// query exchange for fees (invoice coins). Networking involved @MainActor func checkPeerPullCreditM(_ amount: Amount, exchangeBaseUrl: String?) // M for MainActor - async throws -> CheckPeerPullCreditResponse { + async throws -> CheckPeerPullCreditResponse { let request = CheckPeerPullCredit(exchangeBaseUrl: exchangeBaseUrl, amount: amount) let response = try await sendRequest(request, ASYNCDELAY) return response @@ -150,7 +161,7 @@ extension WalletModel { /// generate peer-pull. Networking involved @MainActor func initiatePeerPullCreditM(_ baseURL: String?, terms: PeerContractTerms) // M for MainActor - async throws -> PeerPullResponse { + async throws -> InitiatePeerPullCreditResponse { let request = InitiatePeerPullCredit(exchangeBaseUrl: baseURL, partialContractTerms: terms) let response = try await sendRequest(request, ASYNCDELAY) @@ -160,9 +171,17 @@ extension WalletModel { /// prepare peer-pull. Networking involved @MainActor func preparePeerPushCreditM(_ talerUri: String) // M for MainActor - async throws -> PreparePeerPushCreditResponse { + async throws -> PreparePeerPushCreditResponse { let request = PreparePeerPushCredit(talerUri: talerUri) let response = try await sendRequest(request, ASYNCDELAY) return response } + /// confirm peer-pull. Networking involved + @MainActor + func confirmPeerPushCreditM(_ transactionId: String) // M for MainActor + async throws -> Decodable { + let request = ConfirmPeerPushCredit(transactionId: transactionId) + let response = try await sendRequest(request, ASYNCDELAY) + return response + } } diff --git a/TalerWallet1/Model/Model+Withdraw.swift b/TalerWallet1/Model/Model+Withdraw.swift @@ -82,7 +82,6 @@ fileprivate struct GetExchangeTermsOfService: WalletBackendFormattedRequest { var exchangeBaseUrl: String } } -// MARK: - /// A request to mark an exchange's terms of service as accepted. fileprivate struct SetExchangeTOSAccepted: WalletBackendFormattedRequest { struct Response: Decodable {} diff --git a/TalerWallet1/Views/HelperViews/QRCodeDetailView.swift b/TalerWallet1/Views/HelperViews/QRCodeDetailView.swift @@ -8,7 +8,7 @@ import AVFoundation struct QRCodeDetailView: View { - @Binding var talerURI: String + let talerURI: String let incoming: Bool var body: some View { @@ -44,7 +44,7 @@ fileprivate struct ContentView: View { var body: some View { List { - QRCodeDetailView(talerURI: $talerURI, incoming: false) + QRCodeDetailView(talerURI: talerURI, incoming: false) } } } diff --git a/TalerWallet1/Views/Payment/PaymentURIView.swift b/TalerWallet1/Views/Payment/PaymentURIView.swift @@ -3,7 +3,6 @@ * See LICENSE.md */ import SwiftUI -import AVFoundation import SymLog // Will be called either by the user scanning a QR code or tapping the provided link, both from the shop's website @@ -17,13 +16,9 @@ struct PaymentURIView: View { @State var detailsForUri: PaymentDetailsForUri? = nil func playSound(success: Bool) { -// let url = URL(fileURLWithPath: "/System/Library/Audio/UISounds/PaymentReceived.caf") - let url = URL(fileURLWithPath: "/System/Library/Audio/UISounds/payment_" + (success ? "success.caf" - : "failure.caf")) - var soundID: SystemSoundID = 0 - AudioServicesCreateSystemSoundID(url as CFURL, &soundID) - print(soundID) - AudioServicesPlaySystemSound(soundID); + let url = URL(fileURLWithPath: "/System/Library/Audio/UISounds/payment_" + + (success ? "success.caf" : "failure.caf")) + GNU_Taler.playSound(fileURL: url) } func acceptAction() { diff --git a/TalerWallet1/Views/Peer2peer/SendNow.swift b/TalerWallet1/Views/Peer2peer/SendNow.swift @@ -20,32 +20,32 @@ struct SendNow: View { @State var talerURI: String = "" var body: some View { - ScrollView { + VStack { if talerURI.isEmpty { LoadingView(backButtonHidden: true) } else { - VStack() { - QRCodeDetailView(talerURI: $talerURI, incoming: amountToSend == nil) - + QRCodeDetailView(talerURI: talerURI, + incoming: amountToSend == nil) + .padding() Text("The QR code can also be copied and shared from Transactions later") .fixedSize(horizontal: false, vertical: true) .font(.subheadline) .padding(.vertical, 20) + Spacer() Button("Done") { - ViewState.shared.popToRootView() + withAnimation(){ ViewState.shared.popToRootView() } } .buttonStyle(TalerButtonStyle(type: .prominent)) - .padding(.vertical) + .padding() - } - .interactiveDismissDisabled() // can only use "Done" button to dismiss - .navigationBarHidden(true) // no back button, no title - .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading) - .padding(.horizontal) - .background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.all)) } } +// .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading) +// .padding(.horizontal) + .interactiveDismissDisabled() // can only use "Done" button to dismiss + .navigationBarHidden(true) // no back button, no title + .background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.all)) .task { symLog.log(".task") do { diff --git a/TalerWallet1/Views/Sheets/P2P_Sheets/P2pAcceptDone.swift b/TalerWallet1/Views/Sheets/P2P_Sheets/P2pAcceptDone.swift @@ -10,13 +10,18 @@ struct P2pAcceptDone: View { private let symLog = SymLogV() let navTitle = String(localized: "Received P2P") - let exchangeBaseUrl: String? - let url: URL + let transactionId: String @EnvironmentObject private var model: WalletModel - @State private var confirmTransferUrl: String? = nil - @State private var transactionId: String? = nil + @State private var finished: Bool = false + + func playSound(success: Bool) { + let url = URL(fileURLWithPath: "/System/Library/Audio/UISounds/" + + (success ? "PaymentReceived.caf" + : "payment_failure.caf")) + GNU_Taler.playSound(fileURL: url) + } func reloadOneAction(_ transactionId: String) async throws -> Transaction { return try await model.getTransactionByIdT(transactionId) @@ -28,29 +33,23 @@ struct P2pAcceptDone: View { let _ = symLog.vlog() // just to get the # to compare it with .onAppear & onDisappear #endif VStack { - if let transactionId { - TransactionDetailView(transactionId: transactionId, - reloadAction: reloadOneAction, - doneAction: { dismissTop() }) - .navigationBarBackButtonHidden(true) - .interactiveDismissDisabled() // can only use "Done" button to dismiss - .navigationTitle(navTitle) - } else { - WithdrawProgressView(message: "Bank Confirmation") - .navigationTitle("Loading...") - } + TransactionDetailView(transactionId: transactionId, + reloadAction: reloadOneAction, + doneAction: { dismissTop() }) + .navigationBarBackButtonHidden(true) + .interactiveDismissDisabled() // can only use "Done" button to dismiss + .navigationTitle(navTitle) }.onAppear() { symLog.log("onAppear") DebugViewC.shared.setSheetID(SHEET_RCV_P2P_ACCEPT) }.task { do { - if let exchangeBaseUrl { - let result = try await model.sendAcceptIntWithdrawalM(exchangeBaseUrl, withdrawURL: url.absoluteString) - confirmTransferUrl = result!.confirmTransferUrl - transactionId = result!.transactionId - } + _ = try await model.confirmPeerPushCreditM(transactionId) + finished = true + playSound(success: true) } catch { // TODO: error symLog.log(error.localizedDescription) + playSound(success: false) } } } @@ -58,7 +57,6 @@ struct P2pAcceptDone: View { // MARK: - struct P2pAcceptDone_Previews: PreviewProvider { static var previews: some View { - P2pAcceptDone(exchangeBaseUrl: DEMOEXCHANGE, - url: URL(string: DEMOSHOP)!) + P2pAcceptDone(transactionId: "some ID") } } diff --git a/TalerWallet1/Views/Sheets/P2P_Sheets/P2pPayURIView.swift b/TalerWallet1/Views/Sheets/P2P_Sheets/P2pPayURIView.swift @@ -0,0 +1,85 @@ +/* + * This file is part of GNU Taler, ©2022-23 Taler Systems S.A. + * See LICENSE.md + */ +import SwiftUI +import taler_swift +import SymLog + +// Will be called either by the user scanning a QR code or tapping the provided link, +// from another user's SendInvoice. We show the P2P details. +struct P2pPayURIView: View { + private let symLog = SymLogV() + let navTitle = String(localized: "Pay P2P Invoice") + + // the URL from the bank website + let url: URL + @EnvironmentObject private var model: WalletModel + + @State private var peerPullDebitResponse: PreparePeerPullDebitResponse? + + var body: some View { + let badURL = "Error in URL: \(url)" + VStack { + if let peerPullDebitResponse { + List { + let raw = peerPullDebitResponse.amountRaw + let effective = peerPullDebitResponse.amountEffective + let currency = raw.currencyStr + let fee = try! Amount.diff(raw, effective) + let outColor = WalletColors().transactionColor(false) + let inColor = WalletColors().transactionColor(true) + + ThreeAmountsView(topTitle: String(localized: "Amount to receive:"), + topAmount: raw, fee: fee, + bottomTitle: String(localized: "\(currency) to be obtained:"), + bottomAmount: effective, + large: false, pending: false, incoming: true, + baseURL: nil) + } + .navigationTitle(navTitle) + let tosAccepted = true // TODO: https://bugs.gnunet.org/view.php?id=7869 + if tosAccepted { + NavigationLink(destination: LazyView { + P2pAcceptDone(transactionId: peerPullDebitResponse.transactionId) + }) { + Text("Confirm Withdrawal") // SHEET_WITHDRAW_ACCEPT + }.buttonStyle(TalerButtonStyle(type: .prominent)) + .padding() + } else { + NavigationLink(destination: LazyView { + WithdrawTOSView(exchangeBaseUrl: nil, + viewID: SHEET_RCV_P2P_TOS, + acceptAction: nil) // pop back to here + }) { + Text("Check Terms of Service") + }.buttonStyle(TalerButtonStyle(type: .prominent)) + .padding() + } + } else { + // Yikes no details or no baseURL + // WithdrawProgressView(message: url.host ?? badURL) + // .navigationTitle("Contacting Exchange") + } + } + .onAppear() { + symLog.log("onAppear") + DebugViewC.shared.setSheetID(SHEET_RCV_P2P) + } + .task { + do { // TODO: cancelled + symLog.log(".task") + let ppDebitResponse = try await model.preparePeerPushCreditM(url.absoluteString) + peerPullDebitResponse = ppDebitResponse + } catch { // TODO: error + symLog.log(error.localizedDescription) + peerPullDebitResponse = nil + } + } + + } +} +// MARK: - +//#Preview { +// P2pPayURIView(url: <#T##URL#>, model: <#T##WalletModel#>) +//} diff --git a/TalerWallet1/Views/Sheets/P2P_Sheets/P2pReceiveURIView.swift b/TalerWallet1/Views/Sheets/P2P_Sheets/P2pReceiveURIView.swift @@ -41,7 +41,7 @@ struct P2pReceiveURIView: View { let tosAccepted = true // TODO: https://bugs.gnunet.org/view.php?id=7869 if tosAccepted { NavigationLink(destination: LazyView { - P2pAcceptDone(exchangeBaseUrl: nil, url: url) + P2pAcceptDone(transactionId: peerPushCreditResponse.transactionId) }) { Text("Confirm Withdrawal") // SHEET_WITHDRAW_ACCEPT }.buttonStyle(TalerButtonStyle(type: .prominent))