PayView.swift (3216B)
1 // 2 // PayView.swift 3 // lightninglink 4 // 5 // Created by William Casarin on 2022-02-05. 6 // 7 8 import SwiftUI 9 10 11 struct PayView: View { 12 var invoice_str: String 13 var amount: InvoiceAmount 14 var lnlink: LNLink 15 16 @State var pay_result: Pay? 17 @State var error: String? 18 19 @Environment(\.presentationMode) var presentationMode 20 21 init(invoice_str: String, amount: InvoiceAmount, lnlink: LNLink) { 22 self.invoice_str = invoice_str 23 self.amount = amount 24 self.lnlink = lnlink 25 } 26 27 var successView: some View { 28 VStack() { 29 Text("Payment Success!").font(.largeTitle) 30 } 31 } 32 33 var failView: some View { 34 VStack() { 35 Text("Payment Failed").font(.largeTitle) 36 Text(self.error!) 37 } 38 } 39 40 private func dismiss() { 41 self.presentationMode.wrappedValue.dismiss() 42 } 43 44 var body: some View { 45 return VStack() { 46 Text("Confirm payment") 47 .font(.largeTitle) 48 Spacer() 49 Text("Pay") 50 Text("\(render_amount(self.amount))") 51 .font(.title) 52 Text("\(self.error ?? "")") 53 .foregroundColor(Color.red) 54 Spacer() 55 HStack { 56 Button("Cancel") { 57 self.dismiss() 58 } 59 .font(.title) 60 61 Spacer() 62 63 Button("Confirm") { 64 let res = confirm_payment(bolt11: self.invoice_str, lnlink: self.lnlink) 65 66 switch res { 67 case .left(let err): 68 self.error = "Error: \(err)" 69 70 case .right(let pay): 71 print(pay) 72 self.dismiss() 73 NotificationCenter.default.post(name: .sentPayment, object: pay) 74 } 75 } 76 .font(.title) 77 } 78 } 79 .padding() 80 } 81 } 82 83 /* 84 struct PayView_Previews: PreviewProvider { 85 @Binding var invoice: Invoice? 86 87 static var previews: some View { 88 PayView(invoice: self.$invoice) 89 } 90 } 91 92 93 */ 94 95 public enum Either<L, R> { 96 case left(L) 97 case right(R) 98 } 99 100 func confirm_payment(bolt11: String, lnlink: LNLink) -> Either<String, Pay> { 101 // do a fresh connection for each payment 102 let ln = LNSocket() 103 104 guard ln.connect_and_init(node_id: lnlink.node_id, host: lnlink.host) else { 105 return .left("Failed to connect, please try again!") 106 } 107 108 let res = rpc_pay( 109 ln: ln, 110 token: lnlink.token, 111 bolt11: bolt11, 112 amount_msat: nil) 113 114 switch res { 115 case .failure(let req_err): 116 // handle error 117 let errmsg = req_err.decoded?.message ?? req_err.description 118 return .left(errmsg) 119 120 case .success(let pay): 121 return .right(pay) 122 } 123 } 124 125 126 func render_amount(_ amt: InvoiceAmount) -> String { 127 switch amt { 128 case .any: 129 return "Enter amount" 130 case .amount(let amt): 131 return "\(render_amount_msats(amt))?" 132 } 133 } 134 135 func render_amount_msats(_ amount: Int64) -> String { 136 if amount < 1000 { 137 return "\(amount) msats" 138 } 139 140 return "\(amount / 1000) sats" 141 }