lnlink

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

AmountInputView.swift (2802B)


      1 //
      2 //  AmountInput.swift
      3 //  lightninglink
      4 //
      5 //  Created by William Casarin on 2022-03-25.
      6 //
      7 
      8 import SwiftUI
      9 import Combine
     10 
     11 enum BTCDenomination: String {
     12     case sats
     13     case bits
     14     case mbtc
     15     case btc
     16 }
     17 
     18 enum Denomination: CustomStringConvertible, Identifiable, Hashable {
     19     case fiat(Currency)
     20     case bitcoin(BTCDenomination)
     21 
     22     var description: String {
     23         switch self {
     24         case .fiat(let cur):
     25             return cur.rawValue
     26         case .bitcoin(let btc):
     27             return btc.rawValue
     28         }
     29     }
     30 
     31     var id: String {
     32         return self.description
     33     }
     34 }
     35 
     36 func get_preferred_denominations() -> [Denomination] {
     37     let fiat_pref_str = UserDefaults.standard.string(forKey: "fiat_denomination") ?? "USD"
     38     let btc_pref_str = UserDefaults.standard.string(forKey: "btc_denomination") ?? "sats"
     39 
     40     let btc_pref = BTCDenomination(rawValue: btc_pref_str) ?? .sats
     41     let fiat_pref = Currency(rawValue: fiat_pref_str) ?? .USD
     42 
     43     return [.bitcoin(btc_pref), .fiat(fiat_pref)]
     44 }
     45 
     46 struct ParsedAmount {
     47     let msats_str: String?
     48     let msats: Int64?
     49 
     50     static var empty: ParsedAmount {
     51         ParsedAmount(msats_str: nil, msats: nil)
     52     }
     53 }
     54 
     55 struct AmountInput: View {
     56     @State var amount_msat: Int64? = nil
     57     let text: Binding<String>
     58     let placeholder: String
     59     let onReceive: (ParsedAmount) -> ()
     60 
     61     var body: some View {
     62         VStack {
     63             HStack(alignment: .lastTextBaseline) {
     64                 TextField(placeholder, text: self.text)
     65                     .font(.largeTitle.bold())
     66                     .keyboardType(.numberPad)
     67                     .multilineTextAlignment(.trailing)
     68                     .onReceive(Just(self.text)) {
     69                         onReceive(parse_msat_input($0.wrappedValue))
     70                     }
     71                 Text("sats")
     72                     .font(.subheadline)
     73             }
     74 
     75         }
     76     }
     77 }
     78 
     79 
     80 func msats_to_fiat(msats: Int64, xr: ExchangeRate) -> String {
     81     let btc = Double(msats) / Double(100_000_000_000)
     82     let rate = xr.rate * btc
     83     let num_fmt = NumberFormatter()
     84     num_fmt.numberStyle = .currency
     85     return num_fmt.string(from: NSNumber(value: round(rate * 100) / 100.0))!
     86 }
     87 
     88 
     89 func parse_msat_input(_ new_val: String) -> ParsedAmount {
     90     if new_val == "" {
     91         return ParsedAmount(msats_str: "", msats: nil)
     92     }
     93 
     94     let ok = new_val.allSatisfy { $0 == "," || ($0 >= "0" && $0 <= "9") }
     95     if ok {
     96         let num_fmt = NumberFormatter()
     97         num_fmt.numberStyle = .decimal
     98 
     99         let filtered = new_val.filter { $0 >= "0" && $0 <= "9" }
    100         let sats = Int64(filtered) ?? 0
    101         let msats = sats * 1000
    102         let ret = num_fmt.string(from: NSNumber(value: sats)) ?? new_val
    103         return ParsedAmount(msats_str: ret, msats: msats)
    104     }
    105 
    106     return .empty
    107 }
    108