From b9ed3a97f076537713281bf8a65be925c9054e13 Mon Sep 17 00:00:00 2001 From: Fonta1n3 Date: Tue, 23 Jul 2024 13:43:27 -0400 Subject: [PATCH 1/4] feat: add share button to invoices, add qr scan button next to address inputs, auto reconnect nostr, add nostr status toggle on invoice, increase tor timeout to 60 seconds, show exploded addressess, fix bug where balances were doubling, add donation address button when adding output, add padding to spinner on history view, fix bug where adding inputs would require invoice amount to be accounted for not the additional output amount --- UnifyWallet/BitcoinCore/BitcoinCoreRPC.swift | 24 +++--- UnifyWallet/Extensions.swift | 14 ++++ UnifyWallet/Keys.swift | 19 +++++ UnifyWallet/Views/History/HistoryView.swift | 3 +- .../Receive Child Views/InvoiceView.swift | 57 +++++++++++++-- .../ReceiveAddInputView.swift | 4 +- .../ReceiveAddOutputView.swift | 52 ++++++++++++- UnifyWallet/Views/Receive/ReceiveView.swift | 73 +++++++++++++++++-- UnifyWallet/Views/Send/SendView.swift | 3 +- .../Sending Child Views/BroadcastView.swift | 9 +-- .../Sending Child Views/SendUtxoView.swift | 11 ++- .../SignedProposalView.swift | 4 +- 12 files changed, 232 insertions(+), 41 deletions(-) diff --git a/UnifyWallet/BitcoinCore/BitcoinCoreRPC.swift b/UnifyWallet/BitcoinCore/BitcoinCoreRPC.swift index 168c489..25f7ac3 100644 --- a/UnifyWallet/BitcoinCore/BitcoinCoreRPC.swift +++ b/UnifyWallet/BitcoinCore/BitcoinCoreRPC.swift @@ -58,18 +58,18 @@ class BitcoinCoreRPC { } var request = URLRequest(url: url) - var timeout = 10.0 - - switch method.stringValue { - case "gettxoutsetinfo": - timeout = 1000.0 - - case "importmulti", "deriveaddresses", "loadwallet": - timeout = 60.0 - - default: - break - } + let timeout = 60.0 + +// switch method.stringValue { +// case "gettxoutsetinfo": +// timeout = 1000.0 +// +// case "importmulti", "deriveaddresses", "loadwallet": +// timeout = 60.0 +// +// default: +// break +// } let loginString = String(format: "%@:%@", "PayJoin", rpcPass) let loginData = loginString.data(using: String.Encoding.utf8)! diff --git a/UnifyWallet/Extensions.swift b/UnifyWallet/Extensions.swift index bfa3fe0..649831b 100644 --- a/UnifyWallet/Extensions.swift +++ b/UnifyWallet/Extensions.swift @@ -22,6 +22,19 @@ public extension String { let components = self.components(separatedBy: .whitespacesAndNewlines) return components.filter { !$0.isEmpty }.joined(separator: " ") } + + var withSpaces: String { + var addressToDisplay = "" + for (i, c) in self.enumerated() { + addressToDisplay += "\(c)" + if i > 0 && i < self.count - 2 { + if i.isMultiple(of: 4) { + addressToDisplay += " - " + } + } + } + return addressToDisplay + } } @@ -42,6 +55,7 @@ public extension Double { var btcBalanceWithSpaces: String { var btcBalance = abs(self.rounded(toPlaces: 8)).avoidNotation btcBalance = btcBalance.replacingOccurrences(of: ",", with: "") + if !btcBalance.contains(".") { btcBalance += ".0" } diff --git a/UnifyWallet/Keys.swift b/UnifyWallet/Keys.swift index 4b4a476..ae8b877 100644 --- a/UnifyWallet/Keys.swift +++ b/UnifyWallet/Keys.swift @@ -11,6 +11,25 @@ import LibWally enum Keys { + static func donationAddress() -> String? { + let randomInt = Int.random(in: 0..<100) + + + + let networkSetting = UserDefaults.standard.object(forKey: "network") as? String ?? "Signet" + var network: Network = .testnet + + if networkSetting == "Mainnet" { + network = .mainnet + } + + guard let hdKey = try? HDKey(base58: "xpub6C1DcRZo4RfYHE5F4yiA2m26wMBLr33qP4xpVdzY1EkHyUdaxwHhAvAUpohwT4ajjd1N9nt7npHrjd3CLqzgfbEYPknaRW8crT2C9xmAy3G"), + let path = try? BIP32Path(string: "0/\(randomInt)"), + let address = try? hdKey.derive(using: path).address(type: .payToWitnessPubKeyHash), let x = try? Address(scriptPubKey: address.scriptPubKey, network: network) else { return nil } + + return x.description + } + static func seed() -> String? { var words: String? let bytesCount = 32 diff --git a/UnifyWallet/Views/History/HistoryView.swift b/UnifyWallet/Views/History/HistoryView.swift index 12bbfc9..6ea2d07 100644 --- a/UnifyWallet/Views/History/HistoryView.swift +++ b/UnifyWallet/Views/History/HistoryView.swift @@ -32,7 +32,8 @@ struct HistoryView: View { Image(systemName: "arrow.clockwise") .foregroundStyle(.blue) } - } + .padding(.trailing) + } } Form() { List() { diff --git a/UnifyWallet/Views/Receive/Receive Child Views/InvoiceView.swift b/UnifyWallet/Views/Receive/Receive Child Views/InvoiceView.swift index d158545..50ff06c 100644 --- a/UnifyWallet/Views/Receive/Receive Child Views/InvoiceView.swift +++ b/UnifyWallet/Views/Receive/Receive Child Views/InvoiceView.swift @@ -29,6 +29,9 @@ struct InvoiceView: View, DirectMessageEncrypting { @State private var showingPassphraseAlert = false @State private var passphrase = "" @State private var passphraseConfirm = "" + @State private var nostrConnected = false + @State var startDate = Date.now + @State var timeElapsed: Int = 0 let invoiceAmount: Double @@ -41,6 +44,26 @@ struct InvoiceView: View, DirectMessageEncrypting { var body: some View { Form() { + let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect() + + Toggle("Nostr status", isOn: $nostrConnected) + .onChange(of: nostrConnected) { oldValue, newValue in + if !newValue { + StreamManager.shared.closeWebSocket() + } else { + if StreamManager.shared.webSocket == nil { + connectToNostr() + } + } + } + .onReceive(timer) { firedDate in + timeElapsed = Int(firedDate.timeIntervalSince(startDate)) + if timeElapsed.isMultiple(of: 10) { + nostrConnected = StreamManager.shared.webSocket != nil + } + + } + if let ourKeypair = ourKeypair { let url = "bitcoin:\(invoiceAddress)?amount=\(invoiceAmount)&pj=nostr:\(ourKeypair.publicKey.npub)" @@ -69,6 +92,8 @@ struct InvoiceView: View, DirectMessageEncrypting { } label: { Image(systemName: "doc.on.doc") } + + ShareLink("Share", item: standardInvoice) } HStack() { @@ -80,7 +105,7 @@ struct InvoiceView: View, DirectMessageEncrypting { .foregroundStyle(.blue) } - Text(invoiceAddress) + Text(invoiceAddress.withSpaces) } HStack() { @@ -121,6 +146,8 @@ struct InvoiceView: View, DirectMessageEncrypting { } label: { Image(systemName: "doc.on.doc") } + + ShareLink("Share", item: url) } HStack() { @@ -132,7 +159,7 @@ struct InvoiceView: View, DirectMessageEncrypting { .foregroundStyle(.blue) } - Text(invoiceAddress) + Text(invoiceAddress.withSpaces) } HStack() { @@ -240,6 +267,9 @@ struct InvoiceView: View, DirectMessageEncrypting { } else { HStack() { ProgressView() + #if os(macOS) + .scaleEffect(0.5) + #endif Text(" Waiting on response from sender...") .foregroundStyle(.secondary) @@ -273,7 +303,10 @@ struct InvoiceView: View, DirectMessageEncrypting { txSent = false ourKeypair = nil ourKeypair = Keypair() - connectToNostr() + if StreamManager.shared.webSocket == nil { + connectToNostr() + } + }) .alert(errorToDisplay, isPresented: $showError) { Button("OK", role: .cancel) {} @@ -289,7 +322,6 @@ struct InvoiceView: View, DirectMessageEncrypting { .textFieldStyle(.roundedBorder) .frame(maxWidth: .infinity, maxHeight: .infinity) .padding(EdgeInsets(top: 12, leading: 12, bottom: 12, trailing: 12)) - //} } @@ -330,11 +362,15 @@ struct InvoiceView: View, DirectMessageEncrypting { private func connectToNostr() { StreamManager.shared.openWebSocket(relayUrlString: urlString, peerNpub: nil, p: ourKeypair!.publicKey.hex) - StreamManager.shared.eoseReceivedBlock = { _ in } + StreamManager.shared.eoseReceivedBlock = { _ in + nostrConnected = true + } StreamManager.shared.errorReceivedBlock = { nostrError in if nostrError != "" { showError(desc: nostrError) + nostrConnected = false + StreamManager.shared.closeWebSocket() } } @@ -414,9 +450,7 @@ struct InvoiceView: View, DirectMessageEncrypting { return } - print("invoiceAddress: \(invoiceAddress)") // Failing for regtest address :( - let invoiceAddress = try! Address(string: invoiceAddress) var allInputsSegwit = false @@ -612,6 +646,11 @@ struct QRView: View { } label: { Image(systemName: "doc.on.doc") } + + ShareLink(item: Image(uiImage: image), preview: SharePreview("Invoice", image: Image(uiImage: image))) { + Label("Share", systemImage: "square.and.arrow.up") + } + } .alert("Invoice copied ✓", isPresented: $showCopiedAlert) { Button("OK", role: .cancel) { } @@ -635,6 +674,10 @@ struct QRView: View { } label: { Image(systemName: "doc.on.doc") } + + ShareLink(item: Image(nsImage: image), preview: SharePreview("Invoice", image: Image(nsImage: image))) { + Label("Share", systemImage: "square.and.arrow.up") + } } .alert("Invoice copied ✓", isPresented: $showCopiedAlert) { diff --git a/UnifyWallet/Views/Receive/Receive Child Views/ReceiveAddInputView.swift b/UnifyWallet/Views/Receive/Receive Child Views/ReceiveAddInputView.swift index 8e77692..02cd1fa 100644 --- a/UnifyWallet/Views/Receive/Receive Child Views/ReceiveAddInputView.swift +++ b/UnifyWallet/Views/Receive/Receive Child Views/ReceiveAddInputView.swift @@ -34,7 +34,7 @@ struct ReceiveAddInputView: View { Section() { ForEach(utxos, id:\.self) { utxo in let amt = utxo.amount!.btcBalanceWithSpaces - let addr = utxo.address! + let addr = utxo.address!.withSpaces let txt = addr + " " + amt Text(txt) } @@ -42,7 +42,7 @@ struct ReceiveAddInputView: View { Text("Select utxo's to pay the output") } footer: { - if totalAmtSelected > invoiceAmount { + if totalAmtSelected > outputAmount { NavigationLink(value: ReceiveNavigationLinkValues.invoiceView(invoiceAmount: invoiceAmount, invoiceAddress: invoiceAddress, additionalInputs: utxosToSpend, diff --git a/UnifyWallet/Views/Receive/Receive Child Views/ReceiveAddOutputView.swift b/UnifyWallet/Views/Receive/Receive Child Views/ReceiveAddOutputView.swift index 47a893e..308d415 100644 --- a/UnifyWallet/Views/Receive/Receive Child Views/ReceiveAddOutputView.swift +++ b/UnifyWallet/Views/Receive/Receive Child Views/ReceiveAddOutputView.swift @@ -14,6 +14,7 @@ struct ReceiveAddOutputView: View { @State private var additionalOutputAddress = "" @State private var additionalOutputAmount = "" @State private var spendableAmount = 0.0 + @State private var isShowingScanner = false let invoiceAmount: Double @@ -35,7 +36,7 @@ struct ReceiveAddOutputView: View { Section() { HStack() { - Label("BTC Amount", systemImage: "bitcoinsign.circle") + Label("Amount", systemImage: "bitcoinsign.circle") .frame(maxWidth: 200, alignment: .leading) Spacer() @@ -47,7 +48,7 @@ struct ReceiveAddOutputView: View { } HStack() { - Label("Recipient address", systemImage: "arrow.down.forward.circle") + Label("Address", systemImage: "arrow.down.forward.circle") .frame(maxWidth: 200, alignment: .leading) Spacer() @@ -58,6 +59,29 @@ struct ReceiveAddOutputView: View { #endif .autocorrectionDisabled() + + #if os(iOS) + Button { + isShowingScanner = true + } label: { + Image(systemName: "qrcode.viewfinder") + } + .sheet(isPresented: $isShowingScanner) { + CodeScannerView(codeTypes: [.qr], simulatedData: "", completion: handleScan) + } + #endif + } + + if additionalOutputAddress != "" { + Text(additionalOutputAddress.withSpaces) + } else { + Button { + guard let donationAddress = Keys.donationAddress() else { return } + + additionalOutputAddress = donationAddress + } label: { + Text("Donation address") + } } } header: { Text("Additional Output") @@ -109,6 +133,30 @@ struct ReceiveAddOutputView: View { } +#if os(iOS) + func handleScan(result: Result) { + isShowingScanner = false + switch result { + case .success(let result): + let invoice = Invoice(result.string) + guard let address = invoice.address, + let amount = invoice.amount else { + + self.additionalOutputAddress = result.string + + return + } + + self.additionalOutputAddress = address + self.additionalOutputAmount = "\(amount)" + + case .failure(let error): + print("Scanning failed: \(error.localizedDescription)") + } + } +#endif + + private func getSpendableAmount() { for input in utxos { spendableAmount += input.amount! diff --git a/UnifyWallet/Views/Receive/ReceiveView.swift b/UnifyWallet/Views/Receive/ReceiveView.swift index e3ea9d5..9278079 100644 --- a/UnifyWallet/Views/Receive/ReceiveView.swift +++ b/UnifyWallet/Views/Receive/ReceiveView.swift @@ -19,6 +19,9 @@ struct ReceiveView: View { @State private var torEnabled = false @State private var showSpinner = false @State private var balance = 0.0 + @State private var fetchingBalance = false + @State private var fetchingAddress = false + @State private var isShowingScanner = false var body: some View { @@ -36,12 +39,24 @@ struct ReceiveView: View { } Section("Balance") { - Label(balance.btcBalanceWithSpaces, systemImage: "bitcoinsign.circle") + HStack() { + Label(balance.btcBalanceWithSpaces, systemImage: "bitcoinsign.circle") + + if fetchingBalance { + Spacer() + + ProgressView() + #if os(macOS) + .scaleEffect(0.5) + #endif + } + } + } Section("Create Invoice") { HStack() { - Label("Invoice amount", systemImage: "bitcoinsign.circle") + Label("Amount", systemImage: "bitcoinsign.circle") .frame(maxWidth: 200, alignment: .leading) Spacer() @@ -53,7 +68,7 @@ struct ReceiveView: View { } HStack() { - Label("Invoice address", systemImage: "arrow.down.forward.circle") + Label("Address", systemImage: "arrow.down.forward.circle") .frame(maxWidth: 200, alignment: .leading) Spacer() @@ -64,7 +79,18 @@ struct ReceiveView: View { #endif .autocorrectionDisabled() - if !showSpinner { + #if os(iOS) + Button { + isShowingScanner = true + } label: { + Image(systemName: "qrcode.viewfinder") + } + .sheet(isPresented: $isShowingScanner) { + CodeScannerView(codeTypes: [.qr], simulatedData: "", completion: handleScan) + } + #endif + + if !fetchingAddress { Button { fetchAddress() } label: { @@ -72,7 +98,7 @@ struct ReceiveView: View { } } - if showSpinner { + if fetchingAddress { ProgressView() #if os(macOS) .scaleEffect(0.5) @@ -81,6 +107,10 @@ struct ReceiveView: View { #endif } } + + if address != "" { + Text(address.withSpaces) + } } if let amountDouble = Double(amount), amountDouble > 0 && address != "" { @@ -164,6 +194,30 @@ struct ReceiveView: View { } +#if os(iOS) + func handleScan(result: Result) { + isShowingScanner = false + switch result { + case .success(let result): + let invoice = Invoice(result.string) + guard let address = invoice.address, + let amount = invoice.amount else { + + self.address = result.string + + return + } + + self.address = address + self.amount = "\(amount)" + + case .failure(let error): + print("Scanning failed: \(error.localizedDescription)") + } + } +#endif + + private func displayError(desc: String) { errDesc = desc showError = true @@ -171,10 +225,12 @@ struct ReceiveView: View { private func fetchAddress() { - showSpinner = true + fetchingAddress = true let p = Get_New_Address(["address_type": "bech32"]) BitcoinCoreRPC.shared.btcRPC(method: .getnewaddress(param: p)) { (response, errorDesc) in + self.fetchingAddress = false + guard let address = response as? String else { displayError(desc: errorDesc ?? "Unknown error from getnewaddress.") showSpinner = false @@ -182,16 +238,19 @@ struct ReceiveView: View { } self.address = address - self.showSpinner = false } } private func getUtxos() { + fetchingBalance = true + balance = 0.0 let p = List_Unspent([:]) utxos.removeAll() BitcoinCoreRPC.shared.btcRPC(method: .listunspent(p)) { (response, errorDesc) in + fetchingBalance = false + guard let response = response as? [[String: Any]] else { displayError(desc: errorDesc ?? "Unknown error from listunspent.") //showSpinner = false diff --git a/UnifyWallet/Views/Send/SendView.swift b/UnifyWallet/Views/Send/SendView.swift index 7d325ef..63da14c 100644 --- a/UnifyWallet/Views/Send/SendView.swift +++ b/UnifyWallet/Views/Send/SendView.swift @@ -48,7 +48,7 @@ struct SendView: View, DirectMessageEncrypting { } else { Section("Pay Invoice") { if let uploadedInvoice = uploadedInvoice { - Label("\(uploadedInvoice.address!)", systemImage: "arrow.up.forward.circle") + Label("\(uploadedInvoice.address!.withSpaces)", systemImage: "arrow.up.forward.circle") Label(uploadedInvoice.amount!.btcBalanceWithSpaces, systemImage: "bitcoinsign.circle") } @@ -105,6 +105,7 @@ struct SendView: View, DirectMessageEncrypting { private func getUtxos() { + balance = 0.0 let p = List_Unspent([:]) utxos.removeAll() diff --git a/UnifyWallet/Views/Send/Sending Child Views/BroadcastView.swift b/UnifyWallet/Views/Send/Sending Child Views/BroadcastView.swift index 182f8e8..00130a7 100644 --- a/UnifyWallet/Views/Send/Sending Child Views/BroadcastView.swift +++ b/UnifyWallet/Views/Send/Sending Child Views/BroadcastView.swift @@ -31,6 +31,9 @@ struct BroadcastView: View, DirectMessageEncrypting { if sending { VStack() { ProgressView() + #if os(macOS) + .scaleEffect(0.5) + #endif } .alert(errorDesc, isPresented: $showError) { Button("OK", role: .cancel) {} @@ -47,7 +50,7 @@ struct BroadcastView: View, DirectMessageEncrypting { .font(.title) .fontWeight(.bold) - Text("Send \(invoice.amount!.btcBalanceWithSpaces) to \(invoice.address!)? This is final!") + Text("Send \(invoice.amount!.btcBalanceWithSpaces) to \(invoice.address!.withSpaces)? This is final!") .font(.body) .multilineTextAlignment(.center) .padding(.horizontal, 40) @@ -82,10 +85,6 @@ struct BroadcastView: View, DirectMessageEncrypting { .frame(width: 200, height: 200.0) .aspectRatio(contentMode: .fit) - Text("Broadcast ✓") - .font(.title) - .fontWeight(.bold) - Text(txid) .font(.body) .multilineTextAlignment(.center) diff --git a/UnifyWallet/Views/Send/Sending Child Views/SendUtxoView.swift b/UnifyWallet/Views/Send/Sending Child Views/SendUtxoView.swift index 0d36696..e5099c6 100644 --- a/UnifyWallet/Views/Send/Sending Child Views/SendUtxoView.swift +++ b/UnifyWallet/Views/Send/Sending Child Views/SendUtxoView.swift @@ -69,7 +69,7 @@ struct SendUtxoView: View, DirectMessageEncrypting { .font(.title) .fontWeight(.bold) - Text("Send \(invoice.amount!.btcBalanceWithSpaces) to \(invoice.address!)?") + Text("Send \(invoice.amount!.btcBalanceWithSpaces) to \(invoice.address!.withSpaces)?") .font(.body) .multilineTextAlignment(.center) .padding(.horizontal, 40) @@ -293,7 +293,11 @@ struct SendUtxoView: View, DirectMessageEncrypting { } StreamManager.shared.errorReceivedBlock = { nostrError in - showError(desc: "Nostr received error: \(nostrError)") + //showError(desc: "Nostr received error: \(nostrError)") + errorToDisplay = nostrError + showError = true + StreamManager.shared.closeWebSocket() + StreamManager.shared.openWebSocket(relayUrlString: urlString, peerNpub: recipientsNpub, p: nil) } StreamManager.shared.onDoneBlock = { nostrResponse in @@ -572,5 +576,8 @@ struct SendUtxoView: View, DirectMessageEncrypting { struct Spinner: View { var body: some View { ProgressView("Waiting for payjoin proposal") + #if os(macOS) + .scaleEffect(0.5) + #endif } } diff --git a/UnifyWallet/Views/Send/Sending Child Views/SignedProposalView.swift b/UnifyWallet/Views/Send/Sending Child Views/SignedProposalView.swift index 88ccf15..f1b6221 100644 --- a/UnifyWallet/Views/Send/Sending Child Views/SignedProposalView.swift +++ b/UnifyWallet/Views/Send/Sending Child Views/SignedProposalView.swift @@ -126,7 +126,7 @@ struct SignedProposalView: View, DirectMessageEncrypting { VStack(alignment: .trailing) { if bold { - Text(outputAddress) + Text(outputAddress.withSpaces) .bold(bold) .foregroundStyle(.primary) @@ -135,7 +135,7 @@ struct SignedProposalView: View, DirectMessageEncrypting { .foregroundStyle(.primary) } else { - Text(outputAddress) + Text(outputAddress.withSpaces) .bold(bold) .foregroundStyle(.secondary) From 9bcd7c26cdd77ee4a19bab5448a98d337965690e Mon Sep 17 00:00:00 2001 From: Fonta1n3 Date: Tue, 23 Jul 2024 13:43:52 -0400 Subject: [PATCH 2/4] feat: demo mode --- UnifyWallet/UnifyWalletApp.swift | 69 ++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 7 deletions(-) diff --git a/UnifyWallet/UnifyWalletApp.swift b/UnifyWallet/UnifyWalletApp.swift index ceacfb7..d1f7b07 100644 --- a/UnifyWallet/UnifyWalletApp.swift +++ b/UnifyWallet/UnifyWalletApp.swift @@ -21,6 +21,9 @@ struct UnifyWalletApp: App { var body: some Scene { WindowGroup { HomeView() + #if os(iOS) + .onAppear(perform: UIApplication.shared.addTapGestureRecognizer) + #endif } } @@ -55,10 +58,37 @@ struct UnifyWalletApp: App { return } + // MARK: Normal flow +// UserDefaults.standard.setValue("38332", forKey: "rpcPort") +// UserDefaults.standard.setValue("Signet", forKey: "network") +// +// guard let encRpcPass = Crypto.encrypt(Crypto.privKeyData()) else { +// showNotSavedAlert = true +// return +// } +// +// let dict: [String:Any] = [ +// "rpcPass": encRpcPass, +// "rpcUser": "Unify", +// "rpcAddress": "127.0.0.1", +// "rpcPort": "38332" +// ] + + // MARK: Demo mode + guard let rpcauthcreds = RPCAuth().generateCreds(username: "Unify", password: "1d52e89e0c16a7cc57cbda4954eebf4ba7864e113e5c8bbaa8ab662c8af9ce91") else { + showNotSavedAlert = true + return + } + UserDefaults.standard.setValue("38332", forKey: "rpcPort") UserDefaults.standard.setValue("Signet", forKey: "network") - - guard let encRpcPass = Crypto.encrypt(Crypto.privKeyData()) else { + UserDefaults.standard.setValue(true, forKey: "torEnabled") + UserDefaults.standard.setValue("FullyNoded-da09e4c7b0fc6187c2c1bd2ace56bad7ba25406da168d7b16b4793ef81a082f9", forKey: "walletName") + // Specify a wallet too. + + let rpcpass = rpcauthcreds.password + + guard let encRpcPass = Crypto.encrypt(rpcpass.data(using: .utf8)!) else { showNotSavedAlert = true return } @@ -66,13 +96,19 @@ struct UnifyWalletApp: App { let dict: [String:Any] = [ "rpcPass": encRpcPass, "rpcUser": "Unify", - "rpcAddress": "127.0.0.1", + "rpcAddress": "rarokrtgsiwy42pcgmrp2sdslrt2efpt56rbhjvnwjnje2os64p3t5qd.onion", "rpcPort": "38332" ] - - saveCreds(entityName: "RPCCredentials", dict: dict) - - createDefaultTorCreds() + + let d = Data("smile pool offer seat betray sponsor build genius vault follow glad near".utf8) + guard let encryptedSigner = Crypto.encrypt(d) else { return } + DataManager.saveEntity(entityName: "BIP39Signer", dict: ["encryptedData": encryptedSigner]) { signerSaved in + guard signerSaved else { return } + + saveCreds(entityName: "RPCCredentials", dict: dict) + + createDefaultTorCreds() + } return } @@ -112,3 +148,22 @@ struct UnifyWalletApp: App { } } } + +#if os(iOS) +extension UIApplication { + func addTapGestureRecognizer() { + guard let window = windows.first else { return } + let tapGesture = UITapGestureRecognizer(target: window, action: #selector(UIView.endEditing)) + tapGesture.requiresExclusiveTouchType = false + tapGesture.cancelsTouchesInView = false + tapGesture.delegate = self + window.addGestureRecognizer(tapGesture) + } +} + +extension UIApplication: UIGestureRecognizerDelegate { + public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { + return true // set to `false` if you don't want to detect tap during other gestures + } +} +#endif From bd5d4e700e0f40baab43f8e8cdee12ec30e4b8ea Mon Sep 17 00:00:00 2001 From: Fonta1n3 Date: Tue, 23 Jul 2024 14:08:50 -0400 Subject: [PATCH 3/4] chore: update macos product version --- UnifyWallet.xcodeproj/project.pbxproj | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/UnifyWallet.xcodeproj/project.pbxproj b/UnifyWallet.xcodeproj/project.pbxproj index 0c716d1..6ed9500 100644 --- a/UnifyWallet.xcodeproj/project.pbxproj +++ b/UnifyWallet.xcodeproj/project.pbxproj @@ -922,7 +922,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = UnifyWallet/UnifyWallet.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"UnifyWallet/Preview Content\""; DEVELOPMENT_TEAM = 8JHDU5M9KD; ENABLE_HARDENED_RUNTIME = YES; @@ -950,7 +950,7 @@ "LD_RUNPATH_SEARCH_PATHS[sdk=iphoneos*]" = "@executable_path/Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 14.0; - MARKETING_VERSION = 1.0.1; + MARKETING_VERSION = 0.0.2; PRODUCT_BUNDLE_IDENTIFIER = com.dentonllc.UnifyWallet; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = auto; @@ -971,7 +971,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = UnifyWallet/UnifyWallet.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"UnifyWallet/Preview Content\""; DEVELOPMENT_TEAM = 8JHDU5M9KD; ENABLE_HARDENED_RUNTIME = YES; @@ -998,7 +998,7 @@ LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 14.0; - MARKETING_VERSION = 1.0.1; + MARKETING_VERSION = 0.0.2; PRODUCT_BUNDLE_IDENTIFIER = com.dentonllc.UnifyWallet; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = auto; @@ -1046,7 +1046,7 @@ "LD_RUNPATH_SEARCH_PATHS[sdk=iphoneos*]" = "@executable_path/Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 14.0; - MARKETING_VERSION = 0.0.1; + MARKETING_VERSION = 0.0.2; PRODUCT_BUNDLE_IDENTIFIER = com.dentonllc.UnifyWallet; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = auto; @@ -1092,7 +1092,7 @@ LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 14.0; - MARKETING_VERSION = 0.0.1; + MARKETING_VERSION = 0.0.2; PRODUCT_BUNDLE_IDENTIFIER = com.dentonllc.UnifyWallet; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = auto; From cfe747e77ec8fcc7a6ba078c68a2763ec5fa6e51 Mon Sep 17 00:00:00 2001 From: Fonta1n3 Date: Wed, 24 Jul 2024 10:12:05 -0400 Subject: [PATCH 4/4] fix: padding on refresh history spinner --- UnifyWallet.xcodeproj/project.pbxproj | 20 ++++++++++---------- UnifyWallet/Views/History/HistoryView.swift | 1 + 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/UnifyWallet.xcodeproj/project.pbxproj b/UnifyWallet.xcodeproj/project.pbxproj index 6ed9500..55dd57d 100644 --- a/UnifyWallet.xcodeproj/project.pbxproj +++ b/UnifyWallet.xcodeproj/project.pbxproj @@ -225,7 +225,7 @@ 0A832A532C33906D00F25C46 /* DescriptorInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DescriptorInfo.swift; sourceTree = ""; }; 0A832A552C3395A500F25C46 /* Keys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Keys.swift; sourceTree = ""; }; 0A832A572C33B1D400F25C46 /* NetworkInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkInfo.swift; sourceTree = ""; }; - 0A9AB0F52C3B198E002551E2 /* UnifyWalletmacOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UnifyWalletmacOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 0A9AB0F52C3B198E002551E2 /* UnifyWalletDesktop.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UnifyWalletDesktop.app; sourceTree = BUILT_PRODUCTS_DIR; }; 2A0C438B71D5FD0248DF6734 /* Pods_UnifyWalletmacOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_UnifyWalletmacOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 560ADF9DDDB431D7C6A7E9BC /* Pods_UnifyWallet.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_UnifyWallet.framework; sourceTree = BUILT_PRODUCTS_DIR; }; AE13A5377A734BAA9755D892 /* Pods-UnifyWallet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UnifyWallet.debug.xcconfig"; path = "Target Support Files/Pods-UnifyWallet/Pods-UnifyWallet.debug.xcconfig"; sourceTree = ""; }; @@ -285,7 +285,7 @@ isa = PBXGroup; children = ( 0A8329C82C29F00F00F25C46 /* UnifyWallet.app */, - 0A9AB0F52C3B198E002551E2 /* UnifyWalletmacOS.app */, + 0A9AB0F52C3B198E002551E2 /* UnifyWalletDesktop.app */, ); name = Products; sourceTree = ""; @@ -506,9 +506,9 @@ productReference = 0A8329C82C29F00F00F25C46 /* UnifyWallet.app */; productType = "com.apple.product-type.application"; }; - 0A9AB0B12C3B198E002551E2 /* UnifyWalletmacOS */ = { + 0A9AB0B12C3B198E002551E2 /* UnifyWalletDesktop */ = { isa = PBXNativeTarget; - buildConfigurationList = 0A9AB0F22C3B198E002551E2 /* Build configuration list for PBXNativeTarget "UnifyWalletmacOS" */; + buildConfigurationList = 0A9AB0F22C3B198E002551E2 /* Build configuration list for PBXNativeTarget "UnifyWalletDesktop" */; buildPhases = ( CCFC471BD4CF29F863132118 /* [CP] Check Pods Manifest.lock */, 0A9AB0B62C3B198E002551E2 /* Sources */, @@ -521,13 +521,13 @@ ); dependencies = ( ); - name = UnifyWalletmacOS; + name = UnifyWalletDesktop; packageProductDependencies = ( 0A9AB0B22C3B198E002551E2 /* NostrSDK */, 0A9AB0B42C3B198E002551E2 /* SwiftUICoreImage */, ); productName = UnifyWallet; - productReference = 0A9AB0F52C3B198E002551E2 /* UnifyWalletmacOS.app */; + productReference = 0A9AB0F52C3B198E002551E2 /* UnifyWalletDesktop.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -563,7 +563,7 @@ projectRoot = ""; targets = ( 0A8329C72C29F00F00F25C46 /* UnifyWallet */, - 0A9AB0B12C3B198E002551E2 /* UnifyWalletmacOS */, + 0A9AB0B12C3B198E002551E2 /* UnifyWalletDesktop */, ); }; /* End PBXProject section */ @@ -1019,7 +1019,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = UnifyWallet/UnifyWallet.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEVELOPMENT_ASSET_PATHS = "\"UnifyWallet/Preview Content\""; DEVELOPMENT_TEAM = 8JHDU5M9KD; ENABLE_HARDENED_RUNTIME = YES; @@ -1066,7 +1066,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = UnifyWallet/UnifyWallet.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEVELOPMENT_ASSET_PATHS = "\"UnifyWallet/Preview Content\""; DEVELOPMENT_TEAM = 8JHDU5M9KD; ENABLE_HARDENED_RUNTIME = YES; @@ -1125,7 +1125,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 0A9AB0F22C3B198E002551E2 /* Build configuration list for PBXNativeTarget "UnifyWalletmacOS" */ = { + 0A9AB0F22C3B198E002551E2 /* Build configuration list for PBXNativeTarget "UnifyWalletDesktop" */ = { isa = XCConfigurationList; buildConfigurations = ( 0A9AB0F32C3B198E002551E2 /* Debug */, diff --git a/UnifyWallet/Views/History/HistoryView.swift b/UnifyWallet/Views/History/HistoryView.swift index 6ea2d07..582f40d 100644 --- a/UnifyWallet/Views/History/HistoryView.swift +++ b/UnifyWallet/Views/History/HistoryView.swift @@ -25,6 +25,7 @@ struct HistoryView: View { #if os(macOS) .scaleEffect(0.5) #endif + .padding(.trailing) } else { Button() { listTransactions()