lnlink

iOS app for connecting to lightning nodes
git clone git://jb55.com/lnlink
Log | Files | Refs | Submodules | README

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 }