Add LND test wallet

This commit is contained in:
adrianaepure
2023-06-08 09:36:06 +03:00
commit 1313d727cf
251 changed files with 57518 additions and 0 deletions

View File

@ -0,0 +1,431 @@
//
// ChannelsVC.swift
// wallet
//
// Created by Adriana Epure on 22.08.2022.
// Copyright © 2022 Jason. All rights reserved.
//
import UIKit
class ChannelsVC: CustomViewController<ChannelsViewModel> {
private let nodeKeyPlaceholder: String = "Public Node Key ..."
@IBOutlet weak var selectedListControl: UISegmentedControl!
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var channelsBtnsStack: UIStackView!
@IBOutlet weak var availableBalanceLbl: UILabel!
//MARK: Open Channel Outlets
@IBOutlet weak var newStackView: UIStackView!
@IBOutlet weak var newBtn: UIButton!
@IBOutlet weak var openAddressTextView: UITextView!
@IBOutlet weak var openBtn: UIButton!
@IBOutlet weak var cancelOpen: UIButton!
@IBOutlet weak var localFundingStepper: UIStepper!
@IBOutlet weak var pushAmountStepper: UIStepper!
@IBOutlet weak var localFundingAmount: UITextField!
@IBOutlet weak var closeAddressTextField: UITextField!
@IBOutlet weak var hostAddress: UITextField!
@IBOutlet weak var portTextField: UITextField!
@IBOutlet weak var pushSatAmount: UITextField!
lazy var refreshControl: UIRefreshControl = {
let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action:
#selector(refreshData(_:)),
for: .valueChanged)
refreshControl.tintColor = UIColor.gray
return refreshControl
}()
override func viewDidLoad() {
super.viewDidLoad()
title = "Channels"
self.selectedListControl.selectedSegmentIndex = 0
self.selectedListControl.sendActions(for: .valueChanged)
tableView.delegate = self
tableView.dataSource = self
}
override func viewModelDidLoad() {
viewModel.channels.observe = { [weak self] channels in
self?.tableView.reloadData()
}
viewModel.pendingChannels.observe = { [weak self] channels in
self?.tableView.reloadData()
}
viewModel.closedChannels.observe = { [weak self] channels in
self?.tableView.reloadData()
}
viewModel.peers.observe = { [weak self] peers in
self?.tableView.reloadData()
}
viewModel.walletBalance.observe = { [weak self] walletBalance in
self?.availableBalanceLbl.text = String(walletBalance.total)
}
viewModel.load()
viewModel.getWalletBalance()
self.tableView.addSubview(self.refreshControl)
}
@objc private func refreshData(_ sender: Any) {
// Fetch Weather Data
refreshList()
self.tableView.reloadData()
refreshControl.endRefreshing()
}
//MARK: - New Channel
@IBAction func didPressNewBtn(_ sender: UIButton) {
openAddressTextView.text = nodeKeyPlaceholder
openAddressTextView.textColor = UIColor.lightGray
openAddressTextView.delegate = self
openAddressTextView.layer.borderColor = UIColor.lightGray.cgColor
openAddressTextView.layer.borderWidth = 1
closeAddressTextField.delegate = self
localFundingAmount.delegate = self
pushSatAmount.delegate = self
showHideViews(isNew: true, isFinished: false)
openAddressTextView.text = "0245fc5e867abb5b83ead35b50dc5013dd358b9f3eb48c02f5e1cc9fc675039359"
}
@IBAction func didChangePushSatStepper(_ sender: UIStepper) {
pushSatAmount.text = String(String(format: "%.f", sender.value))
toggleOpenBtn()
}
@IBAction func didChangeLocalFundingStepper(_ sender: UIStepper) {
localFundingAmount.text = String(String(format: "%.f", sender.value))
toggleOpenBtn()
}
@IBAction func didPressOpenBtn(_ sender: UIButton) {
self.selectedListControl.selectedSegmentIndex = 0
self.selectedListControl.sendActions(for: .valueChanged)
if let channelAddress = openAddressTextView.text{
guard let pubKey = openAddressTextView.text else {
return
}
guard let host = hostAddress.text else {
return
}
guard let port = UInt(portTextField.text ?? "") else {
return
}
guard let funding = Int(localFundingAmount.text ?? "") else {
return
}
guard let push = Int(pushSatAmount.text ?? "") else {
return
}
debugPrint("Channel Address ", channelAddress)
viewModel.openChannel(nodePubKey: pubKey, hostAddress: host, port: port, pushSat: push, localFunding: funding) { response in
self.showAlert(title: "Channel Open", errorMsg: "Channel Open Request Sent")
} onFailure: { error in
self.showAlert(title: "Channel Open", errorMsg: "Channel Open Request Failed")
}
}
showHideViews(isNew: true, isFinished: true)
}
@IBAction func didPressCancelOpenBtn(_ sender: UIButton) {
showHideViews(isNew: !newStackView.isHidden, isFinished: true)
}
//MARK: - Selection
@IBAction func didChangeSelection(_ sender: Any) {
refreshList()
tableView.reloadData()
}
}
extension ChannelsVC{
func refreshList(){
switch selectedListControl.selectedSegmentIndex{
case 0:
viewModel.listChannels()
case 1:
viewModel.listClosedChannels()
case 2, 3:
viewModel.listPendingChannels()
default:
viewModel.listPeers()
}
}
func toggleOpenBtn(){
openBtn.isHidden = true
let isNodeKeyFilled = !openAddressTextView.text.isEmpty && openAddressTextView.textColor != UIColor.lightGray
let isCloseAddressFilled = !(closeAddressTextField.text?.isEmpty ?? true)
guard let localFundingText = localFundingAmount.text else {
return
}
guard let pushSatText = pushSatAmount.text else {
return
}
openBtn.isHidden = !(isNodeKeyFilled && Int(localFundingText) ?? 0 > 0 && Int(pushSatText) ?? 0 > 0)
}
func showHideViews(isNew: Bool, isFinished: Bool){
channelsBtnsStack.isHidden = !isFinished
newStackView.isHidden = isFinished || (!isFinished && !isNew)
tableView.isHidden = !isFinished
selectedListControl.isHidden = !isFinished
// openBtn.isHidden = true
if isFinished{
localFundingAmount.text = ""
localFundingAmount.text = "0"
openAddressTextView.text = ""
}
}
}
//MARK: - List
extension ChannelsVC: UITableViewDelegate, UITableViewDataSource{
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
if selectedListControl.selectedSegmentIndex == 0 {
return viewModel.channels.value?[indexPath.row].active ?? false
} else {
return false
}
}
func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
return "Close"
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if selectedListControl.selectedSegmentIndex == 0 && editingStyle == .delete{
if let channel = viewModel.channels.value?[indexPath.row]{
debugPrint(channel)
let showAlert = UIAlertController(title: "Close Channel", message: "Are you sure you want to close this channel?", preferredStyle: .alert)
showAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: { action in
self.viewModel.closeChannel(channel: channel) { response in
self.showAlert(title: "Closed Channel", description: "Channel Close Request Sent")
} onFailure: { error in
self.showAlert(title: "Closed Channel", description: "Channel Close Request Failed")
}
debugPrint("✅✅ Close channel ✅✅")
}))
showAlert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { action in
self.viewModel.listChannels()
}))
self.present(showAlert, animated: true, completion: nil)
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let emptyLabel = UILabel(frame: CGRect(x: 0, y: 0, width: self.view.bounds.size.width, height: self.view.bounds.size.height))
emptyLabel.text = ""
emptyLabel.textAlignment = NSTextAlignment.center
self.tableView.backgroundView = emptyLabel
switch selectedListControl.selectedSegmentIndex{
case 0:
if let noOfChannels = viewModel.channels.value?.count{
return noOfChannels
}else{
emptyLabel.text = "No channels"
self.tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
return 0
}
case 1:
if let noOfClosedChannels = viewModel.closedChannels.value?.count{
return noOfClosedChannels
}else{
emptyLabel.text = "No closed channels"
self.tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
return 0
}
case 2:
if let noOfPendingChannels = viewModel.pendingChannels.value?.pendingOpenChannels.count {
return noOfPendingChannels
}else{
emptyLabel.text = "No pending open channels"
self.tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
return 0
}
case 3:
if let noOfPendingChannels = viewModel.pendingChannels.value?.waitingCloseChannels.count {
return noOfPendingChannels
}else{
emptyLabel.text = "No pending closed channels"
self.tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
return 0
}
default:
if let noOfPeers = viewModel.peers.value?.count{
return noOfPeers
}else{
emptyLabel.text = "No Peers"
self.tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
return 0
}
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let reuseCellIdentifier = "cellIdentifier"
var cell = tableView.dequeueReusableCell(withIdentifier: reuseCellIdentifier)
if (!(cell != nil)) {
cell = UITableViewCell(style: .subtitle, reuseIdentifier: reuseCellIdentifier)
}
cell?.textLabel?.numberOfLines = 0
cell?.detailTextLabel?.numberOfLines = 0
switch selectedListControl.selectedSegmentIndex{
case 0:
if let channel = viewModel.channels.value?[indexPath.row]{
cell?.textLabel?.text = "Status: \(channel.active ? "active" : "inactive") \nFee per Kw: \(channel.feePerKw) sat \nUptime: \(channel.uptime) "
cell?.detailTextLabel?.text = "\nLocal Balance: \(channel.localBalance) sat \nRemote Balance: \(channel.remoteBalance) sat \nUnsettled balance: \(channel.unsettledBalance) sat \nPublic key: \(channel.remotePubkey)"
}
case 1:
if let channel = viewModel.closedChannels.value?[indexPath.row]{
cell?.textLabel?.text = "\nSettled Balance per Kw: \(channel.settledBalance) sat \nCapacity: \(channel.capacity) "
cell?.detailTextLabel?.text = "\nOpen by: \(channel.openInitiator) sat \nClosed by: \(channel.closeInitiator) sat \nTime Locked balance: \(channel.timeLockedBalance) sat \nPublic key: \(channel.remotePubkey)"
}
case 2:
if let channel = viewModel.pendingChannels.value?.pendingOpenChannels[indexPath.row] as? Lnrpc_PendingChannelsResponse.PendingOpenChannel{
debugPrint("Channel pending list", channel, indexPath)
cell?.textLabel?.text = "\n Pending Open "
cell?.detailTextLabel?.text = "\n \nCapacity: \(channel.channel.capacity) \nConfirmation Height \(channel.confirmationHeight) \nLocal Balance: \(channel.channel.localBalance) sat \nRemote Balance: \(channel.channel.remoteBalance) sat \n \(channel.channel.channelPoint)"
}
case 3:
if let channel = viewModel.pendingChannels.value?.waitingCloseChannels[indexPath.row] as? Lnrpc_PendingChannelsResponse.WaitingCloseChannel{
debugPrint("Channel pending list", channel, indexPath)
cell?.textLabel?.text = "\n Pending Close "
cell?.detailTextLabel?.text = "\n \nCapacity: \(channel.channel.capacity) \nLimbo Balance \(channel.limboBalance) \n\nLocal TX ID\(channel.commitments.localTxid) \n\nRemote TX ID\(channel.commitments.remoteTxid) \n\nLocal Commit Fee\(channel.commitments.localCommitFeeSat) sat \nRemote Commit Fee\(channel.commitments.remoteCommitFeeSat) sat \n\nLocal Balance: \(channel.channel.localBalance) sat \nRemote Balance: \(channel.channel.remoteBalance) sat \n \(channel.channel.channelPoint)"
}
default:
if let peer = viewModel.peers.value?[indexPath.row]{
cell?.textLabel?.text = "Received : \(peer.satRecv) sat \nSent: \(peer.satSent) sat "
cell?.detailTextLabel?.text = "\n Host: \(peer.address) \nInbound: \(peer.inbound) \nPing time:\(peer.pingTime) \nPublic key: \(peer.pubKey)"
}
}
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if selectedListControl.selectedSegmentIndex == 0{
if let channel = viewModel.channels.value?[indexPath.row]{
self.viewModel.getChannelInfo(id: channel.chanID) { channelInfo in
debugPrint(channelInfo)
let info = "🕓 Last Update: \(Int64(channelInfo.lastUpdate).getAsDate().format(style: .medium)) \n💰Capacity: \(channelInfo.capacity)sat \n💰 RemoteBalance: \(channel.remoteBalance)sat \n💰Local Balance: \(channel.localBalance)sat \nPoint: \(channelInfo.chanPoint) \n\n✅->>>>>> Node 1 <<<<<<-✅\n\n💰 Base Fee:\(channelInfo.node1Policy.feeBaseMsat)sat\nFee Rate:\(channelInfo.node2Policy.feeRateMilliMsat)msat \nPublic key: \n\(channelInfo.node1Pub) \n\n✅->>>>>> Node 2 <<<<<<-✅\n\n💰 Base Fee:\(channelInfo.node2Policy.feeBaseMsat)sat\nFee Rate:\(channelInfo.node2Policy.feeRateMilliMsat)msat\nPublic key: \n\(channelInfo.node2Pub) "
self.showAlert(title: "Channel Info", description: info)
} onFailure: { error in
debugPrint(error)
}
}
}else{
if let peer = viewModel.peers.value?[indexPath.row]{
self.showAlert(title: "Peer", address: peer.pubKey)
}
}
}
}
extension ChannelsVC: UITextFieldDelegate{
/**
* Called when 'return' key pressed. return NO to ignore.
*/
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
toggleOpenBtn()
textField.resignFirstResponder()
return true
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField == localFundingAmount || textField == pushSatAmount{
let allowedCharacters = CharacterSet.decimalDigits
let characterSet = CharacterSet(charactersIn: string)
return allowedCharacters.isSuperset(of: characterSet)
}
return true
}
/**
* Called when the user click on the view (outside the UITextField).
*/
func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.view.endEditing(true)
}
}
extension ChannelsVC: UITextPasteDelegate {
func textPasteConfigurationSupporting(_ textPasteConfigurationSupporting: UITextPasteConfigurationSupporting, shouldAnimatePasteOf attributedString: NSAttributedString, to textRange: UITextRange) -> Bool {
return false
}
}
extension ChannelsVC: UITextViewDelegate{
func textViewDidBeginEditing(_ textView: UITextView) {
if textView.textColor == UIColor.lightGray {
textView.text = nil
textView.textColor = UIColor.black
}
}
func textViewDidEndEditing(_ textView: UITextView) {
if textView.text.isEmpty {
textView.text = nodeKeyPlaceholder
textView.textColor = UIColor.lightGray
}
}
func textViewDidChange(_ textView: UITextView) {
if(textView.text == UIPasteboard.general.string){
}
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
// Combine the textView text and the replacement text to
// create the updated text string
let currentText:String = textView.text
let updatedText = (currentText as NSString).replacingCharacters(in: range, with: text)
// If updated text view will be empty, add the placeholder
// and set the cursor to the beginning of the text view
if updatedText.isEmpty {
textView.text = nodeKeyPlaceholder
textView.textColor = UIColor.lightGray
textView.selectedTextRange = textView.textRange(from: textView.beginningOfDocument, to: textView.beginningOfDocument)
}
// Else if the text view's placeholder is showing and the
// length of the replacement string is greater than 0, set
// the text color to black then set its text to the
// replacement string
else if textView.textColor == UIColor.lightGray && !text.isEmpty {
textView.textColor = UIColor.black
textView.text = text
}else if text == "\n" {
textView.resignFirstResponder()
toggleOpenBtn()
return false
}
// For every other case, the text should change with the usual
// behavior...
else {
return true
}
// ...otherwise return false since the updates have already
// been made
return false
}
func textViewDidChangeSelection(_ textView: UITextView) {
if self.view.window != nil {
if textView.textColor == UIColor.lightGray {
textView.selectedTextRange = textView.textRange(from: textView.beginningOfDocument, to: textView.beginningOfDocument)
}
}
}
}

View File

@ -0,0 +1,294 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="ChannelsVC" customModule="wallet" customModuleProvider="target">
<connections>
<outlet property="availableBalanceLbl" destination="0rv-hh-yTU" id="YJV-cH-7mD"/>
<outlet property="cancelOpen" destination="1z2-qr-1G2" id="fkX-KG-rol"/>
<outlet property="channelsBtnsStack" destination="h4H-Ut-Ezh" id="D3n-YI-Q04"/>
<outlet property="closeAddressTextField" destination="YYe-rx-c3w" id="JJe-UR-7zE"/>
<outlet property="hostAddress" destination="e2a-MX-Po7" id="Aoh-kM-wEu"/>
<outlet property="localFundingAmount" destination="La5-7h-5LH" id="p0M-ND-iyF"/>
<outlet property="localFundingStepper" destination="Uyt-iD-uLf" id="a0t-cG-U6p"/>
<outlet property="newBtn" destination="u7v-GW-Zcu" id="F1t-0F-Ezn"/>
<outlet property="newStackView" destination="EMx-u0-dZ0" id="gya-ja-rxd"/>
<outlet property="openAddressTextView" destination="HVV-61-fc4" id="ocL-Pq-gXa"/>
<outlet property="openBtn" destination="KXZ-8G-xlK" id="feZ-7c-cVF"/>
<outlet property="portTextField" destination="8Du-rx-ZO7" id="iy7-Iz-xhD"/>
<outlet property="pushAmountStepper" destination="8jb-gN-cXi" id="36O-o0-Gnw"/>
<outlet property="pushSatAmount" destination="Sl9-tu-l5C" id="Lvn-8N-l46"/>
<outlet property="selectedListControl" destination="quV-XT-L9U" id="MNo-Ve-4jN"/>
<outlet property="tableView" destination="CNO-2M-Ehd" id="mpP-7J-tTr"/>
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="15" translatesAutoresizingMaskIntoConstraints="NO" id="EbI-sn-GFX" userLabel="ChannelStack">
<rect key="frame" x="10" y="54" width="394" height="798"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="27A-G6-BKJ">
<rect key="frame" x="0.0" y="0.0" width="394" height="24"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Available Balance:" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Qld-17-jca">
<rect key="frame" x="0.0" y="0.0" width="321.5" height="24"/>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0rv-hh-yTU">
<rect key="frame" x="331.5" y="0.0" width="12.5" height="24"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="20"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="sats" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Poe-ge-Ilm">
<rect key="frame" x="354" y="0.0" width="40" height="24"/>
<constraints>
<constraint firstAttribute="width" constant="40" id="Ei2-DA-alP"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="h4H-Ut-Ezh" userLabel="Channel Buttons">
<rect key="frame" x="0.0" y="39" width="394" height="40"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="u7v-GW-Zcu">
<rect key="frame" x="0.0" y="0.0" width="394" height="40"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="d5o-dh-wsM"/>
</constraints>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="New" cornerStyle="medium">
<color key="baseForegroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="baseBackgroundColor" red="0.36654189230000001" green="0.68308699129999995" blue="0.86276882889999995" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
</buttonConfiguration>
<connections>
<action selector="didPressNewBtn:" destination="-1" eventType="touchUpInside" id="GYC-4M-B4L"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="DtU-1U-uV3">
<rect key="frame" x="0.0" y="94" width="394" height="339.5"/>
<subviews>
<stackView hidden="YES" opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="EMx-u0-dZ0" userLabel="new">
<rect key="frame" x="0.0" y="0.0" width="571" height="310"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" distribution="equalCentering" alignment="center" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="02R-N8-t4A">
<rect key="frame" x="0.0" y="0.0" width="571" height="30"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Funding" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0IX-IG-L1X" userLabel="Funding">
<rect key="frame" x="0.0" y="5" width="61.5" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="20000" borderStyle="roundedRect" placeholder="Amount" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="La5-7h-5LH">
<rect key="frame" x="130.5" y="0.0" width="150" height="30"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="Ecx-Yc-mLv"/>
<constraint firstAttribute="width" constant="150" id="nxL-LP-usf"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits"/>
</textField>
<stepper opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" wraps="YES" value="100" maximumValue="9.2233720368547758e+18" stepValue="100" translatesAutoresizingMaskIntoConstraints="NO" id="Uyt-iD-uLf">
<rect key="frame" x="333.5" y="0.0" width="94" height="30"/>
<connections>
<action selector="didChangeLocalFundingStepper:" destination="-1" eventType="valueChanged" id="DDl-LL-wRZ"/>
</connections>
</stepper>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="sats" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bAR-HI-pY9">
<rect key="frame" x="539.5" y="5" width="31.5" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" distribution="equalCentering" alignment="center" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="221-mN-hvL">
<rect key="frame" x="0.0" y="40" width="571" height="30"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Push Sat" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="CRA-2B-8MY" userLabel="Funding">
<rect key="frame" x="0.0" y="5" width="67.5" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="100" borderStyle="roundedRect" placeholder="Amount" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Sl9-tu-l5C">
<rect key="frame" x="132.5" y="0.0" width="150" height="30"/>
<constraints>
<constraint firstAttribute="width" constant="150" id="Pgn-Fw-60H"/>
<constraint firstAttribute="height" constant="30" id="mN4-at-DVI"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits"/>
</textField>
<stepper opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" wraps="YES" value="100" maximumValue="9.2233720368547758e+18" stepValue="100" translatesAutoresizingMaskIntoConstraints="NO" id="8jb-gN-cXi">
<rect key="frame" x="334.5" y="0.0" width="94" height="30"/>
<connections>
<action selector="didChangePushSatStepper:" destination="-1" eventType="valueChanged" id="u9z-Wi-lz2"/>
</connections>
</stepper>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="sats" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="iaC-rR-77q">
<rect key="frame" x="539.5" y="5" width="31.5" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<textView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" keyboardDismissMode="interactive" text="0245fc5e867abb5b83ead35b50dc5013dd358b9f3eb48c02f5e1cc9fc675039359" textAlignment="natural" adjustsFontForContentSizeCategory="YES" translatesAutoresizingMaskIntoConstraints="NO" id="HVV-61-fc4">
<rect key="frame" x="0.0" y="80" width="571" height="150"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="150" id="KSm-OU-Bqo"/>
</constraints>
<color key="textColor" systemColor="labelColor"/>
<fontDescription key="fontDescription" type="system" weight="light" pointSize="12"/>
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" enablesReturnKeyAutomatically="YES" smartDashesType="no" smartQuotesType="no"/>
</textView>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="02d38c9cdbc94a25438c473f96ba97450ca3897cdd86f4d2e64b04d97830316100" borderStyle="roundedRect" placeholder="Close Address" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="YYe-rx-c3w">
<rect key="frame" x="0.0" y="240" width="571" height="0.0"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" returnKeyType="done" enablesReturnKeyAutomatically="YES"/>
</textField>
<stackView opaque="NO" contentMode="scaleToFill" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="7qb-QX-2IG">
<rect key="frame" x="0.0" y="250" width="571" height="0.0"/>
<subviews>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="bmadesign.go.ro" borderStyle="roundedRect" placeholder="Host Address" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="e2a-MX-Po7">
<rect key="frame" x="0.0" y="0.0" width="491" height="0.0"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" returnKeyType="done" enablesReturnKeyAutomatically="YES"/>
</textField>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="9735" borderStyle="roundedRect" placeholder="Port" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="8Du-rx-ZO7">
<rect key="frame" x="501" y="0.0" width="70" height="0.0"/>
<constraints>
<constraint firstAttribute="width" constant="70" id="vBn-Jn-9fI"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" returnKeyType="done" enablesReturnKeyAutomatically="YES"/>
</textField>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="Srx-Kb-1BK">
<rect key="frame" x="0.0" y="260" width="571" height="50"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="KXZ-8G-xlK">
<rect key="frame" x="0.0" y="0.0" width="571" height="40"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="5t6-4c-88b"/>
</constraints>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Open" cornerStyle="medium">
<color key="baseForegroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="baseBackgroundColor" red="0.36654189230000001" green="0.68308699129999995" blue="0.86276882889999995" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
</buttonConfiguration>
<connections>
<action selector="didPressOpenBtn:" destination="-1" eventType="touchUpInside" id="220-cB-njR"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1z2-qr-1G2">
<rect key="frame" x="0.0" y="50" width="571" height="0.0"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Cancel" cornerStyle="medium">
<color key="baseForegroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="baseBackgroundColor" red="0.36654189230000001" green="0.68308699129999995" blue="0.86276882889999995" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
</buttonConfiguration>
<connections>
<action selector="didPressCancelOpenBtn:" destination="-1" eventType="touchUpInside" id="caA-Xs-gyk"/>
</connections>
</button>
</subviews>
</stackView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</stackView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</stackView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="sDf-4k-ftA" userLabel="List">
<rect key="frame" x="0.0" y="448.5" width="394" height="349.5"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="Gil-tx-Uvy" userLabel="List Stack">
<rect key="frame" x="0.0" y="0.0" width="394" height="349.5"/>
<subviews>
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="bar" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="quV-XT-L9U">
<rect key="frame" x="0.0" y="0.0" width="394" height="41"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="Mo3-l7-4DT"/>
</constraints>
<segments>
<segment title="Active"/>
<segment title="Closed"/>
<segment title="Opening"/>
<segment title="Closing"/>
<segment title="Peers"/>
</segments>
<connections>
<action selector="didChangeSelection:" destination="-1" eventType="valueChanged" id="yLp-lM-nT1"/>
</connections>
</segmentedControl>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" style="insetGrouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" estimatedSectionHeaderHeight="-1" sectionFooterHeight="18" estimatedSectionFooterHeight="-1" translatesAutoresizingMaskIntoConstraints="NO" id="CNO-2M-Ehd">
<rect key="frame" x="0.0" y="50" width="394" height="299.5"/>
</tableView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</stackView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="Gil-tx-Uvy" secondAttribute="bottom" id="3oK-i7-Ini"/>
<constraint firstItem="Gil-tx-Uvy" firstAttribute="leading" secondItem="sDf-4k-ftA" secondAttribute="leading" id="aNV-5U-3Jw"/>
<constraint firstAttribute="trailing" secondItem="Gil-tx-Uvy" secondAttribute="trailing" id="cEr-YJ-KsC"/>
<constraint firstItem="Gil-tx-Uvy" firstAttribute="top" secondItem="sDf-4k-ftA" secondAttribute="top" id="yoS-st-AZ9"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</stackView>
</subviews>
<viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="EbI-sn-GFX" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" constant="10" id="7c8-Qu-hWm"/>
<constraint firstItem="EbI-sn-GFX" firstAttribute="top" secondItem="fnl-2z-Ty3" secondAttribute="top" constant="10" id="I1r-ag-t3I"/>
<constraint firstItem="fnl-2z-Ty3" firstAttribute="bottom" secondItem="EbI-sn-GFX" secondAttribute="bottom" constant="10" id="OUL-fR-h4f"/>
<constraint firstAttribute="trailing" secondItem="EbI-sn-GFX" secondAttribute="trailing" constant="10" id="wsh-qt-mNT"/>
</constraints>
<point key="canvasLocation" x="139" y="96"/>
</view>
</objects>
<resources>
<systemColor name="labelColor">
<color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>

View File

@ -0,0 +1,125 @@
import UIKit
class CustomViewController<VM: ViewModel>: UIViewController {
private lazy var leftNavigationAction: () -> Void = {
self.navigationController?.popViewController(animated: true)
}
var viewModel: VM! {
didSet {
viewModelDidLoad()
}
}
lazy var loadingView: LoadingView = {
return LoadingView()
}()
lazy var errorView: ErrorView = {
return ErrorView()
}()
override func viewDidLoad() {
super.viewDidLoad()
// Create the view model if needed
if (viewModel == nil) {
viewModel = VM()
}
// setTheme()
}
public func showContentView() {
dropViews([errorView, loadingView])
}
public func showLoadingView() {
dropViews([errorView])
addViewIfNeeded(loadingView)
}
public func showErrorView(error: String = .defaultError) {
dropViews([loadingView])
addViewIfNeeded(errorView)
errorView.title = error
}
private func dropViews(_ views: [UIView]) {
views.forEach { view in
view.removeFromSuperview()
}
}
private func addViewIfNeeded(_ subview: UIView) {
if (!view.subviews.contains(subview)) {
view.addSubviewAndFill(subview)
view.bringSubviewToFront(subview)
}
}
func viewModelDidLoad() {
// Empty
}
@objc private func leftAction() {
leftNavigationAction()
}
func setLeftNavigationButton(_ icon: UIImage, action: (() -> Void)? = nil) {
// Attach left action
// Or fallback with a pop
if let leftAction = action {
leftNavigationAction = leftAction
} else {
leftNavigationAction = {
self.navigationController?.popViewController(animated: true)
}
}
navigationItem.leftBarButtonItem = UIBarButtonItem(
image: .back,
style: .plain,
target: self,
action: #selector(CustomViewController.leftAction)
)
}
func showAlert(title: String, address: String? = nil , errorMsg: String? = nil, description: String? = nil){
let showAlert = UIAlertController(title: title, message: errorMsg, preferredStyle: .alert)
if let address = address {
let imageView = UIImageView(frame: CGRect(x: 10, y: 50, width: 250, height: 250))
imageView.image = generateQRCode(from: address)
imageView.layer.magnificationFilter = CALayerContentsFilter.nearest
showAlert.view.addSubview(imageView)
let height = NSLayoutConstraint(item: showAlert.view as Any, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 400)
let width = NSLayoutConstraint(item: showAlert.view as Any, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant:250)
showAlert.view.addConstraint(height)
showAlert.view.addConstraint(width)
showAlert.addAction(UIAlertAction(title: "Copy Address", style: .default, handler: { action in
UIPasteboard.general.string = address
debugPrint("✅✅ Created Invoice ✅✅", address)
}))
}
if let description = description {
showAlert.message = description
}
showAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: { action in
}))
self.present(showAlert, animated: true, completion: nil)
}
func generateQRCode(from string: String) -> UIImage? {
let data = string.data(using: String.Encoding.ascii)
if let QRFilter = CIFilter(name: "CIQRCodeGenerator") {
QRFilter.setValue(data, forKey: "inputMessage")
guard let QRImage = QRFilter.outputImage else {return nil}
return UIImage(ciImage: QRImage)
}
return nil
}
}

View File

@ -0,0 +1,16 @@
//
// Home.swift
// wallet
//
// Created by Adriana Epure on 19.08.2022.
// Copyright © 2022 Jason. All rights reserved.
//
import UIKit
class Home: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .red
}
}

View File

@ -0,0 +1,166 @@
//
// HomeVC.swift
// wallet
//
// Created by Adriana Epure on 19.08.2022.
// Copyright © 2022 Jason. All rights reserved.
//
import UIKit
class HomeVC: CustomViewController<HomeViewModel> {
private let password = "sshhhhhh"
/// LND Status
@IBOutlet weak var debugStatus: UILabel!
@IBOutlet weak var lndStatus: UIImageView!
@IBOutlet weak var syncToChainStatus: UIImageView!
@IBOutlet weak var walletStatus: UIImageView!
/// INFO
@IBOutlet weak var infoStack: UIStackView!
@IBOutlet weak var peersCount: UILabel!
@IBOutlet weak var blockHeightCount: UILabel!
@IBOutlet weak var activeChannelsCount: UILabel!
@IBOutlet weak var inactiveChannelsCount: UILabel!
@IBOutlet weak var pendingChannelsCount: UILabel!
/// Wallet
@IBOutlet weak var walletStack: UIStackView!
@IBOutlet weak var walletBalanceStack: UIStackView!
@IBOutlet weak var createWalletBtn: UIButton!
@IBOutlet weak var unlockWalletBtn: UIButton!
@IBOutlet weak var getBalanceBtn: UIButton!
@IBOutlet weak var walletInfo: UIButton!
@IBOutlet weak var totalAmountLbl: UILabel!
@IBOutlet weak var unconfirmedLbl: UILabel!
@IBOutlet weak var confirmedAmountLbl: UILabel!
@IBOutlet weak var showChannelsBtn: UIButton!
@IBOutlet weak var showPaymentsBtn: UIButton!
//MARK: View LifeCycle
override func viewDidLoad() {
super.viewDidLoad()
title = "Home"
updateStatus()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
subscribe()
}
//MARK: ViewModel
// This will get called when the ViewModel for this ViewController is ready to use
// This gives us a simple place to observe all changes to the datasources
// and can update the views accordingly as they change in real time
override func viewModelDidLoad() {
viewModel.isLoading.observe = { [weak self] isLoading in
if (isLoading) {
self?.showLoadingView()
}else{
self?.showContentView()
}
}
viewModel.walletBalance.observe = { [weak self] balance in
self?.updateBalance(balance)
}
viewModel.newAddress.observe = { [weak self] address in
UIPasteboard.general.string = address
self?.showContentView()
}
viewModel.walletWipe.observe = { _ in
UIControl().sendAction(#selector(NSXPCConnection.suspend), to: UIApplication.shared, for: nil)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
exit(0)
}
}
viewModel.load()
}
//MARK: Button Actions
@IBAction func didPressUnlockBtn(_ sender: Any) {
self.viewModel.unlockWallet(password: self.password)
}
@IBAction func didPressPaymentsBtn(_ sender: Any) {
self.navigationController?.pushViewController(PaymentsVC(), animated: true)
}
@IBAction func didPressChannelsBtn(_ sender: Any) {
self.navigationController?.pushViewController(ChannelsVC(), animated: true)
}
@IBAction func didPressWalletInfo(_ sender: Any) {
let walletAddress = LightningStateMonitor.shared.state.walletInfo.identityPubkey
self.showAlert(title: "My Wallet", address: walletAddress)
}
}
//MARK: Subscribe
extension HomeVC{
private func subscribe() {
EventBus.onMainThread(self, eventType: .lndStateChange) { [weak self] (_) in
self?.updateStatus()
}
EventBus.onMainThread(self, eventType: .lndStopped) { [weak self] (_) in
self?.updateStatus()
}
EventBus.onMainThread(self, eventType: .lndStarted) { [weak self] (_) in
self?.updateStatus()
}
EventBus.onMainThread(self, eventType: .lndRpcReady) { [weak self] (_) in
self?.updateStatus()
}
EventBus.onMainThread(self, eventType: .lndWalletUnlocked) { [weak self] (_) in
self?.updateStatus()
}
}
private func updateStatus() {
debugStatus.text = LightningStateMonitor.shared.state.debuggingStatus.joined(separator: "\n\n")
updateLND(isOn: LightningStateMonitor.shared.state.lndRunning)
updateRPC(isReady: LightningStateMonitor.shared.state.walletInfo.syncedToChain)
updateWallet(isUnlocked: LightningStateMonitor.shared.state.walletUnlocked)
updateInfo()
}
private func updateRPC(isReady: Bool){
self.syncToChainStatus.tintColor = isReady ? .green : .red
self.syncToChainStatus.image = isReady ? UIImage(systemName: "point.3.filled.connected.trianglepath.dotted") : UIImage(systemName: "point.3.connected.trianglepath.dotted")
}
private func updateLND(isOn: Bool){
self.unlockWalletBtn.isHidden = !isOn
self.unlockWalletBtn.isEnabled = isOn
self.lndStatus.tintColor = isOn ? .green : .red
self.lndStatus.image = isOn ? UIImage(systemName: "checkmark.circle.fill") : UIImage(systemName: "checkmark.circle.trianglebadge.exclamationmark")
}
private func updateInfo(){
self.peersCount.text = String(LightningStateMonitor.shared.state.walletInfo.numPeers)
self.blockHeightCount.text = String(LightningStateMonitor.shared.state.walletInfo.blockHeight)
self.activeChannelsCount.text = String(LightningStateMonitor.shared.state.walletInfo.numActiveChannels)
self.inactiveChannelsCount.text = String(LightningStateMonitor.shared.state.walletInfo.numInactiveChannels)
self.pendingChannelsCount.text = String(LightningStateMonitor.shared.state.walletInfo.numPendingChannels)
self.viewModel.getWalletBalance()
}
private func updateBalance(_ balance: WalletBalance){
self.totalAmountLbl.text = String(balance.total)
self.confirmedAmountLbl.text = String(balance.confirmed)
self.unconfirmedLbl.text = String(balance.unconfirmed)
}
private func updateWallet(isUnlocked: Bool){
self.unlockWalletBtn.isHidden = isUnlocked
self.walletStatus.tintColor = isUnlocked ? .green : .red
self.walletStatus.image = isUnlocked ? UIImage(systemName: "lock.open") : UIImage(systemName: "lock")
self.infoStack.isHidden = !isUnlocked
self.walletBalanceStack.isHidden = !isUnlocked
self.walletInfo.isEnabled = isUnlocked
// self.getBalanceBtn.isHidden = !isUnlocked
self.showChannelsBtn.isHidden = !isUnlocked
self.showPaymentsBtn.isEnabled = isUnlocked
}
}

View File

@ -0,0 +1,440 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_5" orientation="portrait" appearance="dark"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
<capability name="Image references" minToolsVersion="12.0"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="HomeVC" customModule="wallet" customModuleProvider="target">
<connections>
<outlet property="activeChannelsCount" destination="zRx-dK-uJE" id="hJw-ZA-d9E"/>
<outlet property="blockHeightCount" destination="5QF-aB-AzD" id="n2p-N1-Tel"/>
<outlet property="confirmedAmountLbl" destination="34J-jN-Q91" id="zpC-6E-Ok0"/>
<outlet property="createWalletBtn" destination="xQO-ma-Ns5" id="K4y-qs-XZ6"/>
<outlet property="debugStatus" destination="mtl-Cw-2ae" id="h4l-VD-qjQ"/>
<outlet property="getBalanceBtn" destination="CMf-Ai-3KB" id="16m-QG-cYf"/>
<outlet property="inactiveChannelsCount" destination="z52-zh-U2d" id="aut-SY-5pH"/>
<outlet property="infoStack" destination="QHZ-Pz-mB5" id="m3u-Ut-eoD"/>
<outlet property="lndStatus" destination="moD-HD-xh0" id="U8Q-r1-S47"/>
<outlet property="peersCount" destination="76Q-p1-XZ1" id="rFt-mP-giC"/>
<outlet property="pendingChannelsCount" destination="r5R-Ev-Seq" id="aw7-R3-fcR"/>
<outlet property="showChannelsBtn" destination="cRk-fH-Sad" id="prH-j5-kr0"/>
<outlet property="showPaymentsBtn" destination="HsC-Xa-Y3H" id="1DT-TI-4Us"/>
<outlet property="syncToChainStatus" destination="3tZ-K3-N1j" id="Wmd-iV-8JM"/>
<outlet property="totalAmountLbl" destination="4pG-Su-HTw" id="2E6-Fd-v27"/>
<outlet property="unconfirmedLbl" destination="oG3-SU-sEx" id="JfP-wy-geo"/>
<outlet property="unlockWalletBtn" destination="8rQ-o3-AmK" id="LpW-s0-hhl"/>
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
<outlet property="walletBalanceStack" destination="g7X-9x-bt4" id="fZ5-98-bOU"/>
<outlet property="walletInfo" destination="UUx-4i-0lO" id="UC6-rd-IRY"/>
<outlet property="walletStack" destination="dOk-rZ-J6T" id="LFC-QZ-tB4"/>
<outlet property="walletStatus" destination="Mga-vz-Vve" id="u4y-bw-Hlj"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="0pU-hv-ExQ">
<rect key="frame" x="10" y="54" width="394" height="788"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="zrD-Fl-hXg" userLabel="StatusStack">
<rect key="frame" x="0.0" y="0.0" width="394" height="60"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="Pwi-0u-4yk">
<rect key="frame" x="0.0" y="15" width="234" height="30"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="moD-HD-xh0">
<rect key="frame" x="0.0" y="2.6666666666666661" width="76.666666666666671" height="24.666666666666671"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" systemColor="systemGrayColor"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="NsX-6W-jbc"/>
</constraints>
<imageReference key="image" image="checkmark.circle.trianglebadge.exclamationmark" catalog="system" symbolScale="small"/>
<preferredSymbolConfiguration key="preferredSymbolConfiguration" scale="small" weight="thin"/>
</imageView>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="3tZ-K3-N1j">
<rect key="frame" x="79.666666666666657" y="3.6666666666666661" width="74.666666666666657" height="22.666666666666671"/>
<color key="tintColor" systemColor="systemGrayColor"/>
<imageReference key="image" image="point.3.connected.trianglepath.dotted" catalog="system" symbolScale="small"/>
<preferredSymbolConfiguration key="preferredSymbolConfiguration" scale="small" weight="thin"/>
</imageView>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Mga-vz-Vve">
<rect key="frame" x="159.33333333333334" y="3" width="74.666666666666657" height="24.333333333333332"/>
<color key="tintColor" systemColor="systemGrayColor"/>
<imageReference key="image" image="lock" catalog="system" symbolScale="small"/>
<preferredSymbolConfiguration key="preferredSymbolConfiguration" scale="small" weight="thin"/>
</imageView>
</subviews>
</stackView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="UUx-4i-0lO" userLabel="Info">
<rect key="frame" x="239" y="0.0" width="60" height="60"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="width" constant="60" id="88V-J5-ieg"/>
<constraint firstAttribute="height" constant="60" id="vZp-sM-V5f"/>
</constraints>
<color key="tintColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<buttonConfiguration key="configuration" style="filled" cornerStyle="capsule">
<imageReference key="image" image="qrcode" catalog="system" symbolScale="medium"/>
<preferredSymbolConfiguration key="preferredSymbolConfigurationForImage" configurationType="pointSize" pointSize="20" scale="large" weight="semibold"/>
<color key="baseForegroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="baseBackgroundColor" systemColor="linkColor"/>
</buttonConfiguration>
<connections>
<action selector="didPressWalletInfo:" destination="-1" eventType="touchUpInside" id="JNL-dT-UCs"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="HsC-Xa-Y3H">
<rect key="frame" x="304" y="5" width="90" height="50"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="width" constant="90" id="9yo-Yc-O4q"/>
<constraint firstAttribute="height" constant="50" id="iEh-z3-hvt"/>
</constraints>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" subtitle="Pay" cornerStyle="capsule">
<imageReference key="image" image="bitcoinsign.circle" catalog="system" symbolScale="large"/>
<preferredSymbolConfiguration key="preferredSymbolConfigurationForImage" configurationType="pointSize" pointSize="20" scale="large" weight="semibold"/>
<color key="baseForegroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="baseBackgroundColor" systemColor="systemOrangeColor"/>
</buttonConfiguration>
<connections>
<action selector="didPressPaymentsBtn:" destination="-1" eventType="touchUpInside" id="LPn-Qm-1PI"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="749" verticalCompressionResistancePriority="749" axis="vertical" distribution="fillEqually" alignment="bottom" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="g7X-9x-bt4" userLabel="Wallet Balance">
<rect key="frame" x="0.0" y="109.66666666666666" width="394" height="140"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="YbH-8J-Eic" userLabel="confirmed">
<rect key="frame" x="242.33333333333337" y="0.0" width="151.66666666666663" height="40"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Confirmed:" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lT4-v6-dVB">
<rect key="frame" x="0.0" y="0.0" width="79" height="40"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="APC-iW-MxF"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="34J-jN-Q91">
<rect key="frame" x="88.999999999999972" y="0.0" width="12.666666666666671" height="40"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="20"/>
<color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="sats" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2Z6-YT-Kob">
<rect key="frame" x="111.66666666666666" y="0.0" width="40" height="40"/>
<constraints>
<constraint firstAttribute="width" constant="40" id="7Nn-QB-LRG"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="Kll-eU-fOU" userLabel="unconfirmed">
<rect key="frame" x="224.66666666666663" y="50" width="169.33333333333337" height="40"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Unconfirmed:" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4SM-6U-tSR">
<rect key="frame" x="0.0" y="0.0" width="96.666666666666671" height="40"/>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="oG3-SU-sEx">
<rect key="frame" x="106.66666666666666" y="0.0" width="12.666666666666671" height="40"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="20"/>
<color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="sats" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="njc-NA-8nJ">
<rect key="frame" x="129.33333333333334" y="0.0" width="40" height="40"/>
<constraints>
<constraint firstAttribute="width" constant="40" id="j6y-xc-Byo"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="8bk-xS-8Ds" userLabel="total">
<rect key="frame" x="276.66666666666669" y="100.00000000000003" width="117.33333333333331" height="40"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Total:" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Bxa-dN-D7e">
<rect key="frame" x="0.0" y="0.0" width="43" height="40"/>
<fontDescription key="fontDescription" type="system" weight="light" pointSize="18"/>
<color key="textColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
<color key="shadowColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<size key="shadowOffset" width="0.0" height="0.0"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4pG-Su-HTw">
<rect key="frame" x="53" y="0.0" width="14.333333333333329" height="40"/>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="22"/>
<color key="textColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
<color key="shadowColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<size key="shadowOffset" width="0.0" height="0.0"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="sats" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dGo-sv-6hu">
<rect key="frame" x="77.333333333333314" y="0.0" width="40" height="40"/>
<constraints>
<constraint firstAttribute="width" constant="40" id="RXw-3N-Uj7"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="light" pointSize="16"/>
<color key="textColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
<color key="shadowColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<size key="shadowOffset" width="0.0" height="0.0"/>
</label>
</subviews>
</stackView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</stackView>
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mtl-Cw-2ae">
<rect key="frame" x="0.0" y="252" width="394" height="0.0"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="dOk-rZ-J6T" userLabel="WalletStack">
<rect key="frame" x="0.0" y="299" width="394" height="40"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="H2Y-SL-XLi" userLabel="Wallet Buttons">
<rect key="frame" x="0.0" y="0.0" width="394" height="40"/>
<subviews>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xQO-ma-Ns5">
<rect key="frame" x="0.0" y="0.0" width="0.0" height="40"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="muc-i9-WwF"/>
</constraints>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Create" cornerStyle="medium">
<color key="baseForegroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="baseBackgroundColor" red="0.36654189230000001" green="0.68308699129999995" blue="0.86276882889999995" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
</buttonConfiguration>
</button>
<button opaque="NO" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="8rQ-o3-AmK">
<rect key="frame" x="0.0" y="0.0" width="394" height="40"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Unlock Wallet" cornerStyle="medium">
<color key="baseForegroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="baseBackgroundColor" red="0.36654189230000001" green="0.68308699129999995" blue="0.86276882889999995" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
</buttonConfiguration>
<connections>
<action selector="didPressUnlockBtn:" destination="-1" eventType="touchUpInside" id="4b5-gu-sMm"/>
</connections>
</button>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CMf-Ai-3KB">
<rect key="frame" x="0.0" y="0.0" width="0.0" height="40"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Balance" cornerStyle="medium">
<color key="baseForegroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="baseBackgroundColor" red="0.36654189230000001" green="0.68308699129999995" blue="0.86276882889999995" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
</buttonConfiguration>
</button>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</stackView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</stackView>
<view contentMode="scaleToFill" horizontalHuggingPriority="248" verticalHuggingPriority="248" horizontalCompressionResistancePriority="748" verticalCompressionResistancePriority="748" translatesAutoresizingMaskIntoConstraints="NO" id="gD8-f1-4TU">
<rect key="frame" x="0.0" y="388.66666666666669" width="394" height="200.00000000000006"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="200" id="628-eh-ADF"/>
</constraints>
</view>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" alignment="top" translatesAutoresizingMaskIntoConstraints="NO" id="QHZ-Pz-mB5" userLabel="InfoStack">
<rect key="frame" x="0.0" y="638" width="394" height="150"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" alignment="top" spacing="30" translatesAutoresizingMaskIntoConstraints="NO" id="xVn-YK-0hG" userLabel="Channels">
<rect key="frame" x="0.0" y="0.0" width="394" height="50"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Channels" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="C0U-J3-vOX">
<rect key="frame" x="0.0" y="0.0" width="67.666666666666671" height="19.333333333333332"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="fG4-Fs-83T">
<rect key="frame" x="97.666666666666657" y="0.0" width="296.33333333333337" height="50"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="5GJ-Z1-dgb" userLabel="Active">
<rect key="frame" x="0.0" y="0.0" width="66.666666666666671" height="50"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Active" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ayo-OT-ABI">
<rect key="frame" x="0.0" y="0.0" width="66.666666666666671" height="20"/>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<color key="textColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zRx-dK-uJE">
<rect key="frame" x="0.0" y="30" width="66.666666666666671" height="20"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="20"/>
<color key="textColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="cGI-uh-7h5" userLabel="Inactive">
<rect key="frame" x="76.666666666666657" y="0.0" width="66.666666666666657" height="50"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Inactive" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="rFx-Ct-9Zm">
<rect key="frame" x="0.0" y="0.0" width="66.666666666666671" height="20"/>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<color key="textColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="z52-zh-U2d">
<rect key="frame" x="0.0" y="30" width="66.666666666666671" height="20"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="20"/>
<color key="textColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="hjZ-X3-0Kf" userLabel="Pending">
<rect key="frame" x="153.33333333333331" y="0.0" width="66.333333333333314" height="50"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Pending" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="JFg-pm-GM8">
<rect key="frame" x="0.0" y="0.0" width="66.333333333333329" height="20"/>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<color key="textColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="r5R-Ev-Seq">
<rect key="frame" x="0.0" y="30" width="66.333333333333329" height="20"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="20"/>
<color key="textColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hxv-8W-wtx">
<rect key="frame" x="229.6666666666666" y="0.0" width="66.666666666666657" height="50"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="infoLight" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="cRk-fH-Sad">
<rect key="frame" x="18" y="9.6666666666666305" width="30.666666666666671" height="30.666666666666671"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<buttonConfiguration key="configuration" style="filled" cornerStyle="capsule">
<color key="baseBackgroundColor" red="0.36654189230000001" green="0.68308699129999995" blue="0.86276882889999995" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
</buttonConfiguration>
<connections>
<action selector="didPressChannelsBtn:" destination="-1" eventType="touchUpInside" id="2by-Nc-Q38"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="cRk-fH-Sad" firstAttribute="centerY" secondItem="hxv-8W-wtx" secondAttribute="centerY" id="91x-dp-SXn"/>
<constraint firstItem="cRk-fH-Sad" firstAttribute="centerX" secondItem="hxv-8W-wtx" secondAttribute="centerX" id="HFS-Wc-T0S"/>
</constraints>
</view>
</subviews>
</stackView>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="hxi-E5-mQF" userLabel="Peers">
<rect key="frame" x="0.0" y="50" width="98" height="50"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Peers:" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Dwh-ZT-Vmb">
<rect key="frame" x="0.0" y="0.0" width="44" height="50"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="yvc-Yu-47d"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<color key="textColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="76Q-p1-XZ1">
<rect key="frame" x="54" y="0.0" width="44" height="50"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="20"/>
<color key="textColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="cZP-5r-IM1" userLabel="Block Height">
<rect key="frame" x="0.0" y="100" width="196.66666666666666" height="50"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Block Height:" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="UMC-sR-S7c">
<rect key="frame" x="0.0" y="0.0" width="93.333333333333329" height="50"/>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<color key="textColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5QF-aB-AzD">
<rect key="frame" x="103.33333333333334" y="0.0" width="93.333333333333343" height="50"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="20"/>
<color key="textColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
</subviews>
</stackView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</stackView>
</subviews>
<viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" systemColor="systemIndigoColor"/>
<constraints>
<constraint firstItem="0pU-hv-ExQ" firstAttribute="top" secondItem="fnl-2z-Ty3" secondAttribute="top" constant="10" id="01s-KR-a0w"/>
<constraint firstItem="0pU-hv-ExQ" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" constant="10" id="eN5-Op-IFT"/>
<constraint firstAttribute="trailing" secondItem="0pU-hv-ExQ" secondAttribute="trailing" constant="10" id="egw-G9-8mQ"/>
<constraint firstItem="fnl-2z-Ty3" firstAttribute="bottom" secondItem="0pU-hv-ExQ" secondAttribute="bottom" constant="20" id="qAQ-eR-X6h"/>
</constraints>
<point key="canvasLocation" x="137.68115942028987" y="71.651785714285708"/>
</view>
</objects>
<resources>
<image name="bitcoinsign.circle" catalog="system" width="128" height="121"/>
<image name="checkmark.circle.trianglebadge.exclamationmark" catalog="system" width="128" height="108"/>
<image name="lock" catalog="system" width="128" height="128"/>
<image name="point.3.connected.trianglepath.dotted" catalog="system" width="128" height="96"/>
<image name="qrcode" catalog="system" width="128" height="114"/>
<systemColor name="linkColor">
<color red="0.0" green="0.47843137254901963" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
<systemColor name="systemGrayColor">
<color red="0.55686274509803924" green="0.55686274509803924" blue="0.57647058823529407" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
<systemColor name="systemIndigoColor">
<color red="0.34509803921568627" green="0.33725490196078434" blue="0.83921568627450982" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
<systemColor name="systemOrangeColor">
<color red="1" green="0.58431372549019611" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
</resources>
</document>

View File

@ -0,0 +1,519 @@
import UIKit
class HomeViewController: CustomViewController<HomeViewModel> {
// private let password = "sshhhhhh"
// private var unlockWallet : UIButton!
// private var getInfo : UIButton!
// private var listChannels : UIButton!
// private var openChannel : UIButton!
// private var showInvoices : UIButton!
// private var showPayments : UIButton!
// private var hideButton : UIButton!
// private var sendPayment : UIButton!
// private var receivePayment : UIButton!
// private var cancel : UIButton!
// private var generateInvoice : UIButton!
// private var payInvoice : UIButton!
// private var debugStatus : UILabel!
// private var resultMessage : UILabel!
// private var balance : UILabel!
// private var invoiceLbl : UILabel!
// var isShowPayments: Bool = true
// lazy var contentViewSize = CGSize(width: self.view.frame.width, height: self.view.frame.height)
// lazy var scrollView: UIScrollView = {
// let view = UIScrollView(frame: .zero)
// view.backgroundColor = .white
// view.frame = self.view.bounds
// view.contentSize = contentViewSize
// view.translatesAutoresizingMaskIntoConstraints = false
// return view
// }()
// lazy var stackView: UIStackView = {
// let stackView = UIStackView()
// stackView.axis = .vertical
// stackView.distribution = .fill
// stackView.alignment = .fill
// stackView.spacing = 10
// stackView.translatesAutoresizingMaskIntoConstraints = false
// return stackView
// }()
// lazy var debugStackView: UIStackView = {
// let stackView = UIStackView()
// stackView.axis = .vertical
// stackView.distribution = .fill
// stackView.alignment = .fill
// stackView.spacing = 10
// stackView.translatesAutoresizingMaskIntoConstraints = false
// return stackView
// }()
// lazy var walletStackView: UIStackView = {
// let stackView = UIStackView()
// stackView.axis = .vertical
// stackView.distribution = .fill
// stackView.alignment = .fill
// stackView.spacing = 10
// stackView.translatesAutoresizingMaskIntoConstraints = false
// return stackView
// }()
// lazy var infoStackView: UIStackView = {
// let stackView = UIStackView()
// stackView.axis = .vertical
// stackView.distribution = .fill
// stackView.alignment = .fill
// stackView.spacing = 10
// stackView.translatesAutoresizingMaskIntoConstraints = false
// return stackView
// }()
// lazy var channelStackView: UIStackView = {
// let stackView = UIStackView()
// stackView.axis = .vertical
// stackView.distribution = .fill
// stackView.alignment = .fill
// stackView.spacing = 10
// stackView.translatesAutoresizingMaskIntoConstraints = false
// return stackView
// }()
// lazy var paymentStackView: UIStackView = {
// let stackView = UIStackView()
// stackView.axis = .vertical
// stackView.distribution = .fill
// stackView.alignment = .fill
// stackView.spacing = 10
// stackView.translatesAutoresizingMaskIntoConstraints = false
// return stackView
// }()
// lazy var sendStackView: UIStackView = {
// let stackView = UIStackView()
// stackView.axis = .horizontal
// stackView.distribution = .fillEqually
// stackView.alignment = .fill
// stackView.spacing = 10
// stackView.translatesAutoresizingMaskIntoConstraints = false
// return stackView
// }()
// let textView: UITextField = {
// let textView = UITextField()
// textView.textAlignment = .left
// textView.layer.cornerRadius = 5.0
// textView.layer.borderWidth = 0.2
// textView.layer.borderColor = UIColor.gray.cgColor
// textView.layer.masksToBounds = true
// textView.tintColor = .black
// textView.translatesAutoresizingMaskIntoConstraints = false //enable autolayout
// textView.heightAnchor.constraint(equalToConstant: 100).isActive = true
// textView.isHidden = true
// textView.placeholder = "Enter Invoice..."
//// textView.text = "lntb2500n1p30mapmpp53jy8q39upxn0acs5a2e0hzducxn25f2r9xrp3y7kyje2ug68t4lqdqgf4jhycmfcqzpgxqrrsssp5qe7unjq3j2lw7f8etvlhsgpac8ec7q7pd3ydx6mmaa33vcjcl5as9qyyssq2w3e8d074cz72tmmne9z7c3j9f9u8n3elc2sgzdm7j760847c5az2ca6900tdg7hx8wnaethzqkq60ym4ug7zrr4mlxyzcc5lrvgwycqmyzteq"
// return textView
// }()
// lazy var tableView: UITableView = {
// let tableView: UITableView = UITableView()
// tableView.backgroundColor = .white
// tableView.translatesAutoresizingMaskIntoConstraints = false
// tableView.heightAnchor.constraint(equalToConstant: 200).isActive = true
// tableView.delegate = self
// tableView.dataSource = self
// return tableView
// }()
//
//
// override func viewDidLoad() {
// super.viewDidLoad()
// title = "LND test"
// view.backgroundColor = .white
// view.addSubview(scrollView)
// scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
// scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
// scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
// scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
// setup()
// scrollView.addSubview(stackView)
//
// stackView.translatesAutoresizingMaskIntoConstraints = false
// stackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor, constant: -40).isActive = true
// stackView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 10).isActive = true
// stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 20).isActive = true
// stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: 20).isActive = true
// stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 10).isActive = true
// updateStatus()
// }
//
// override func viewDidAppear(_ animated: Bool) {
// super.viewDidAppear(animated)
// subscribe()
// }
//
// private func subscribe() {
// EventBus.onMainThread(self, eventType: .lndStateChange) { [weak self] (_) in
// self?.updateStatus()
// }
// EventBus.onMainThread(self, eventType: .lndWalletUnlocked) { [weak self] (_) in
// self?.setupInfo()
// self?.setupChannel()
// self?.walletStackView.isHidden = true
// self?.viewModel.getWalletBalance()
// }
// }
//
// private func updateStatus() {
// if LightningStateMonitor.shared.state.lndRunning {
// setupWallet()
// }
//
// debugStatus.text = LightningStateMonitor.shared.state.debuggingStatus.joined(separator: "\n")
// }
//
// private func createButton(_ title: String, action: @escaping () -> Void) -> UIButton {
// let button = CustomButton(action: action)
// button.title = title
// button.translatesAutoresizingMaskIntoConstraints = false
// button.heightAnchor.constraint(equalToConstant: CGFloat(50)).isActive = true
// return button
// }
//
// private func setup() {
// let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap))
// view.addGestureRecognizer(tap) // Add gesture recognizer to background view
// showLNDStatus()
//
// textView.delegate = self
//
// }
//
// // This will get called when the ViewModel for this ViewController is ready to use
// // This gives us a simple place to observe all changes to the datasources
// // and can update the views accordingly as they change in real time
// override func viewModelDidLoad() {
//
// viewModel.isLoading.observe = { [weak self] isLoading in
// if (isLoading) {
// self?.showLoadingView()
// }
// }
//
// viewModel.randomInt.observe = { [weak self] randomInt in
// self?.showContentView()
// }
//
// viewModel.error.observe = { [weak self] error in
// self?.showErrorView()
// }
//
// viewModel.resultMessage.observe = { [weak self] message in
// self?.resultMessage.text = message
// self?.showContentView()
// }
//
// viewModel.newAddress.observe = { [weak self] address in
// self?.resultMessage.text = address
// UIPasteboard.general.string = address
// self?.showContentView()
// }
//
// viewModel.walletWipe.observe = { _ in
// UIControl().sendAction(#selector(NSXPCConnection.suspend), to: UIApplication.shared, for: nil)
// DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
// exit(0)
// }
// }
// viewModel.payments.observe = { [weak self] payments in
// self?.tableView.reloadData()
// }
// viewModel.channels.observe = { [weak self] payments in
// self?.tableView.reloadData()
// }
// viewModel.balance.observe = { [weak self] balance in
// self?.balance.text = balance
// }
// viewModel.invoice.observe = { [weak self] invoice in
// self?.invoiceLbl.text = invoice
// }
// viewModel.load()
//
// }
//
//}
//extension HomeViewController: UITextFieldDelegate{
// @objc func handleTap() {
// textView.resignFirstResponder() // dismiss keyoard
// }
//
// func textFieldDidBeginEditing(_ textField: UITextField) {
// scrollView.setContentOffset(CGPoint(x: 0, y: textField.frame.height), animated: true)
// }
// func textFieldDidEndEditing(_ textField: UITextField) {
//
// if textField.hasText{
// payInvoice.isHidden = false
// }
// scrollView.setContentOffset(CGPoint(x: 0, y: 0), animated: true)
// }
// func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// textField.resignFirstResponder() // dismiss keyboard
// return true
// }
//}
//extension HomeViewController: UITextPasteDelegate {
// func textPasteConfigurationSupporting(_ textPasteConfigurationSupporting: UITextPasteConfigurationSupporting, shouldAnimatePasteOf attributedString: NSAttributedString, to textRange: UITextRange) -> Bool {
// return false
// }
//}
////MARK: - Wallet Management
//extension HomeViewController{
// private func setupWallet(){
//
// // let createButton = addDebugButton("Create wallet", action: {
// // self.viewModel.createWallet(password: self.password)
// // })
// // let newAddressButton = addDebugButton("New address (copies to clipboard)", action: {
// // self.viewModel.getNewAddress()
// // })
// // let wipeButton = addDebugButton("Wipe (and close) wallet", action: {
// // self.viewModel.wipeWallet()
// // })
// unlockWallet = createButton("Unlock wallet", action: {
// self.viewModel.unlockWallet(password: self.password)
// self.balance = UILabel()
// self.balance.text = "..."
// self.balance.textColor = .blue
// self.balance.translatesAutoresizingMaskIntoConstraints = false
// self.balance.textAlignment = .center
// self.balance.numberOfLines = 0
// self.stackView.addArrangedSubview(self.balance)
// })
// walletStackView.addArrangedSubview(unlockWallet)
//
// stackView.addArrangedSubview(walletStackView)
//
// }
//}
////MARK: - Info
//extension HomeViewController{
// private func showLNDStatus(){
//
// resultMessage = UILabel()
// resultMessage.text = "..."
// resultMessage.translatesAutoresizingMaskIntoConstraints = false
// resultMessage.textColor = Theme.inverseBackgroundColor
// resultMessage.textAlignment = .center
// resultMessage.numberOfLines = 0
//
// debugStatus = UILabel()
// debugStatus.translatesAutoresizingMaskIntoConstraints = false
// debugStatus.textColor = Theme.inverseBackgroundColor
// debugStatus.textAlignment = .center
// debugStatus.numberOfLines = 0
// debugStatus.text = "Debug status"
// debugStackView.addArrangedSubview(resultMessage)
// debugStackView.addArrangedSubview(debugStatus)
// stackView.addArrangedSubview(debugStackView)
// }
// private func setupInfo(){
// getInfo = createButton("Show info", action: {
// self.viewModel.getInfo()
// self.viewModel.getWalletBalance()
// })
// infoStackView.addArrangedSubview(getInfo)
// stackView.addArrangedSubview(infoStackView)
//
// }
//}
//
////MARK: - Channel
//extension HomeViewController{
//
// private func setupChannel(){
// openChannel = createButton("Open channel", action: {
// self.viewModel.openChannel()
// })
// listChannels = createButton("List channels", action: {
// self.isShowPayments = false
// self.showHideViews(showChannels: false, showPayments: true)
// self.viewModel.listChannels()
//
// })
// channelStackView.addArrangedSubview(openChannel)
// channelStackView.addArrangedSubview(listChannels)
// stackView.addArrangedSubview(channelStackView)
//
//
// if viewModel.infoResponse.value?.numActiveChannels == 0 {
// listChannels.isHidden = false
// }else{
// openChannel.isHidden = true
// }
// setupPayments()
// }
//
//}
//
////MARK: - Payments Management
//extension HomeViewController: UITableViewDelegate, UITableViewDataSource{
// func showHideViews(showChannels: Bool, showPayments: Bool){
// let isListShowing = (showChannels == showPayments) && showChannels
// let isOneMissing = (showChannels && !showPayments) || (!showChannels && showPayments)
// self.showPayments.isHidden = !showPayments
// self.listChannels.isHidden = !showChannels
// self.hideButton.isHidden = !isOneMissing
// self.tableView.isHidden = !isOneMissing
// self.debugStackView.isHidden = !isListShowing
// self.infoStackView.isHidden = !isListShowing
// self.sendStackView.isHidden = !isListShowing
// }
// func showHideViews(showPay: Bool, showReceive: Bool){
// let hideOthers = !(showPay || showReceive)
// self.showHideViews(showChannels: hideOthers, showPayments: hideOthers)
// self.sendPayment.isHidden = showPay || showReceive
// self.receivePayment.isHidden = showPay || showReceive
// self.cancel.isHidden = showPay && showReceive
// self.payInvoice.isHidden = true
// self.generateInvoice.isHidden = true
// self.invoiceLbl.isHidden = true
// self.textView.isHidden = !showPay
// self.sendStackView.isHidden = false
//
// }
// private func setupPayments(){
//
// showInvoices = createButton("Show invoices", action: {
// self.viewModel.listInvoices()
// })
// hideButton = createButton("Hide", action: {
// self.showHideViews(showChannels: true, showPayments: true)
// })
// showPayments = createButton("Show Payments History", action: {
// self.isShowPayments = true
// self.showHideViews(showChannels: true, showPayments: false)
// self.viewModel.listPayments()
// })
//
//
// sendPayment = createButton("Send", action: {
// self.showHideViews(showPay: true, showReceive: false)
// })
// receivePayment = createButton("Receive", action: {
// self.showHideViews(showPay: false, showReceive: true)
// self.generateInvoice.isHidden = false
// self.invoiceLbl.isHidden = false
// })
// cancel = createButton("Cancel", action: {
// self.showHideViews(showChannels: true, showPayments: true)
// self.showHideViews(showPay: false, showReceive: false)
// self.cancel.isHidden = true
// })
// generateInvoice = createButton("Generate Invoice", action: {
// self.showHideViews(showChannels: true, showPayments: true)
// self.showHideViews(showPay: false, showReceive: false)
// self.viewModel.createInvoice(amount: 200, comment: self.textView.text ?? "Test")
// self.viewModel.getWalletBalance()
// })
// invoiceLbl = UILabel()
// invoiceLbl.text = "..."
// invoiceLbl.translatesAutoresizingMaskIntoConstraints = false
// invoiceLbl.numberOfLines = 0
//
// payInvoice = createButton("Pay Invoice", action: {
// if let text = self.textView.text{
// debugPrint("Invoice ", text)
// self.viewModel.payInvoice(invoice: text)
//
// }else{
//
// }
//
// self.viewModel.getWalletBalance()
// self.showHideViews(showChannels: true, showPayments: true)
// self.showHideViews(showPay: false, showReceive: false)
//
// })
//
// payInvoice.isHidden = true
// generateInvoice.isHidden = true
// invoiceLbl.isHidden = true
// tableView.isHidden = true
// hideButton.isHidden = true
// cancel.isHidden = true
// paymentStackView.addArrangedSubview(showInvoices)
// paymentStackView.addArrangedSubview(showPayments)
// paymentStackView.addArrangedSubview(hideButton)
//
//
// sendStackView.addArrangedSubview(sendPayment)
// sendStackView.addArrangedSubview(receivePayment)
// sendStackView.addArrangedSubview(cancel)
// sendStackView.addArrangedSubview(generateInvoice)
// sendStackView.addArrangedSubview(payInvoice)
//
// paymentStackView.addArrangedSubview(sendStackView)
// paymentStackView.addArrangedSubview(textView)
// paymentStackView.addArrangedSubview(invoiceLbl)
//
// paymentStackView.addArrangedSubview(tableView)
// stackView.addArrangedSubview(paymentStackView)
// }
//
// func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// if isShowPayments{
// if let noOfPayments = viewModel.payments.value?.count{
// return noOfPayments
// }else{
// let emptyLabel = UILabel(frame: CGRect(x: 0, y: 0, width: self.view.bounds.size.width, height: self.view.bounds.size.height))
// emptyLabel.text = "No Payments"
// emptyLabel.textAlignment = NSTextAlignment.center
// self.tableView.backgroundView = emptyLabel
// self.tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
// return 0
// }
// }else{
// if let noOfChannels = viewModel.channels.value?.count{
// return noOfChannels
// }else{
// let emptyLabel = UILabel(frame: CGRect(x: 0, y: 0, width: self.view.bounds.size.width, height: self.view.bounds.size.height))
// emptyLabel.text = "No Channels"
// emptyLabel.textAlignment = NSTextAlignment.center
// self.tableView.backgroundView = emptyLabel
// self.tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
// return 0
// }
// }
//
//
//
// }
//
// func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// let reuseCellIdentifier = "cellIdentifier"
// var cell = tableView.dequeueReusableCell(withIdentifier: reuseCellIdentifier)
// if (!(cell != nil)) {
//
// cell = UITableViewCell(style: .subtitle, reuseIdentifier: reuseCellIdentifier)
// }
// cell?.textLabel?.numberOfLines = 0
// cell?.detailTextLabel?.numberOfLines = 0
// if isShowPayments{
// if let payment = viewModel.payments.value?[indexPath.row]{
// cell?.textLabel?.text = "Status: \(payment.status) \nAmount: \(payment.value) sat"
// cell?.detailTextLabel?.text = "\nDate: \(Date(timeIntervalSince1970: TimeInterval(payment.creationDate))) \nPayment hash:\n\(payment.paymentRequest.description)"
// }
// }else{
// if let channel = viewModel.channels.value?[indexPath.row]{
// cell?.textLabel?.text = "Active: \(channel.active) \nLocal Balance: \(channel.localBalance) sat \nRemote Balance: \(channel.remoteBalance) sat"
// let pendingTransactions = channel.pendingHtlcs.count == 0 ? "" : "\nPending transactions: \(channel.pendingHtlcs)"
// cell?.detailTextLabel?.text = "\nPub key: \(channel.remotePubkey) \(pendingTransactions)"
// }
// }
//
//
// return cell!
// }
}
public extension String {
func setColor(_ color: UIColor, ofSubstring substring: String) -> NSMutableAttributedString {
let range = (self as NSString).range(of: substring)
let attributedString = NSMutableAttributedString(string: self)
attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: color, range: range)
return attributedString
}
}

View File

@ -0,0 +1,403 @@
//
// PaymentsVC.swift
// wallet
//
// Created by Adriana Epure on 22.08.2022.
// Copyright © 2022 Jason. All rights reserved.
//
import UIKit
import QRCodeScanner
class PaymentsVC: CustomViewController<PaymentsViewModel> {
@IBOutlet weak var paymentElements: UIStackView!
@IBOutlet weak var selectedListControl: UISegmentedControl!
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var paymentButtonsStack: UIStackView!
@IBOutlet weak var localBalanceValue: UILabel!
@IBOutlet weak var remoteBalanceValue: UILabel!
@IBOutlet weak var walletBalanceValue: UILabel!
@IBOutlet weak var estimateFeeValue: UILabel!
@IBOutlet weak var feeStackView: UIStackView!
//Send
@IBOutlet weak var sendStackView: UIStackView!
@IBOutlet weak var sendPaymentAddress: UITextView!
@IBOutlet weak var payBtn: UIButton!
@IBOutlet weak var paymentInfoStack: UIStackView!
@IBOutlet weak var paymentInfoLbl: UILabel!
@IBOutlet weak var memoLbl: UILabel!
@IBOutlet weak var paymentInfoCreated: UILabel!
@IBOutlet weak var paymentInfoExpiry: UILabel!
@IBOutlet weak var cancelPayBtn: UIButton!
//Receive
@IBOutlet weak var receiveStackView: UIStackView!
@IBOutlet weak var invoiceAmount: UITextField!
@IBOutlet weak var invoiceComment: UITextField!
@IBOutlet weak var amountStepper: UIStepper!
@IBOutlet weak var receivePaymentAddress: UITextView!
@IBOutlet weak var generateInvoiceBtn: UIButton!
@IBOutlet weak var cancelReceiveBtn: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
viewModel.getInfo()
title = "Payments"
tableView.delegate = self
tableView.dataSource = self
selectedListControl.selectedSegmentIndex == 0 ? viewModel.listPayments() : viewModel.listInvoices()
}
override func viewModelDidLoad() {
viewModel.invoices.observe = { [weak self] invoices in
self?.tableView.reloadData()
}
viewModel.payments.observe = { [weak self] payments in
self?.tableView.reloadData()
}
viewModel.channelBalance.observe = { [weak self] balance in
self?.localBalanceValue.text = String(balance)
}
viewModel.walletBalance.observe = { [weak self] walletBalance in
self?.walletBalanceValue.text = String(walletBalance.total)
}
viewModel.isLoading.observe = { [weak self] isLoading in
self?.viewModel.updateBalance()
}
viewModel.paymentInfo.observe = { [weak self] paymentInfo in
if let paymentInfo = paymentInfo{
self?.paymentInfoStack.isHidden = false
self?.payBtn.isHidden = false
self?.paymentInfoLbl.text = String(paymentInfo.numSatoshis)
self?.paymentInfoCreated.text = paymentInfo.timestamp.getAsDate().format(style: .medium)
self?.paymentInfoExpiry.text = String(paymentInfo.timestamp.getAsDate().adding(seconds: Int(paymentInfo.expiry)).format(style: .medium))
self?.memoLbl.text = String(paymentInfo.description_p)
}else{
self?.paymentInfoStack.isHidden = true
self?.payBtn.isHidden = true
self?.paymentInfoCreated.text = ""
self?.paymentInfoLbl.text = ""
self?.paymentInfoExpiry.text = ""
self?.memoLbl.text = ""
}
}
viewModel.load()
}
//MARK: - Selection
@IBAction func didChangeSelection(_ sender: Any) {
selectedListControl.selectedSegmentIndex == 0 ? viewModel.listPayments() : viewModel.listInvoices()
tableView.reloadData()
}
@IBAction func didPressCancel(_ sender: Any) {
showHideViews(isSending: !sendStackView.isHidden, isFinished: true)
}
//MARK: - Send
@IBAction func didPressSend(_ sender: Any) {
sendPaymentAddress.text = "Input Address ..."
sendPaymentAddress.textColor = UIColor.lightGray
sendPaymentAddress.delegate = self
sendPaymentAddress.layer.borderColor = UIColor.lightGray.cgColor
sendPaymentAddress.layer.borderWidth = 1
showHideViews(isSending: true, isFinished: false)
}
@IBAction func didPressScan(_ sender: Any) {
// Create an instance of QRCodeScanViewController
let viewController = QRCodeScanViewController.create()
// Set itself as delegate
viewController.delegate = self
// Present the view controller
self.present(viewController, animated: true)
}
@IBAction func didPressPay(_ sender: Any) {
self.selectedListControl.selectedSegmentIndex = 0
self.selectedListControl.sendActions(for: .valueChanged)
if let paymentAddress = sendPaymentAddress.text{
debugPrint("Invoice ", paymentAddress)
self.viewModel.payInvoice(invoice: paymentAddress) { response in
self.showAlert(title: "Payment", errorMsg: "Payment Request Sent")
} onFailure: { error in
self.showAlert(title: "Payment", errorMsg: error.debugDescription)
}
self.showAlert(title: "Payment", errorMsg: "Payment Request Sent")
}else{
self.showAlert(title: "Payment", errorMsg: "Payment Request Failed")
}
showHideViews(isSending: true, isFinished: true)
}
//MARK: - Receive
@IBAction func didPressReceive(_ sender: Any) {
invoiceComment.delegate = self
invoiceAmount.delegate = self
showHideViews(isSending: false, isFinished: false)
}
@IBAction func didUpdateStepper(_ sender: UIStepper) {
invoiceAmount.text = String(String(format: "%.f", sender.value))
estimateFeeValue.text = String(String(format: "%.2f", sender.value/1000))
generateInvoiceBtn.isHidden = false
}
@IBAction func didPressGenerateBtn(_ sender: Any) {
self.selectedListControl.selectedSegmentIndex = 1
self.selectedListControl.sendActions(for: .valueChanged)
guard let amountText = invoiceAmount.text else{
self.showAlert(title: "Invoice", errorMsg: "Empty Amount")
return
}
debugPrint("", amountText)
guard let amount:Int = Int(amountText) else{
self.showAlert(title: "Invoice", errorMsg: "Invalid Amount")
return
}
guard let balance:Int = viewModel.walletBalance.value?.total else {
self.showAlert(title: "Invoice", errorMsg: "Invalid wallet balance")
return
}
if(amount > balance){
self.showAlert(title: "Invoice", errorMsg: "Insufficient funds")
}else if amount == 0{
self.showAlert(title: "Invoice", errorMsg: "No amount selected")
}else{
createInvoice(amount: amount, comment: invoiceComment.text ?? "")
}
showHideViews(isSending: false, isFinished: true)
}
func showHideViews(isSending: Bool, isFinished: Bool){
sendStackView.isHidden = isFinished || (!isFinished && !isSending)
receiveStackView.isHidden = isFinished || (!isFinished && isSending)
feeStackView.isHidden = isFinished || (!isFinished && isSending)
paymentButtonsStack.isHidden = !isFinished
tableView.isHidden = !isFinished
selectedListControl.isHidden = !isFinished
generateInvoiceBtn.isHidden = true
payBtn.isHidden = true
if isFinished{
invoiceComment.text = ""
invoiceAmount.text = "0"
estimateFeeValue.text = "0"
sendPaymentAddress.text = ""
}
}
}
//MARK: - Create Invoice
extension PaymentsVC{
func createInvoice(amount: Int, comment: String){
self.showLoadingView()
viewModel.createInvoice(amount: amount, comment: comment) { paymentRequest in
self.showContentView()
self.showAlert(title: "Invoice", address: paymentRequest)
} onFailure: { error in
self.showContentView()
self.showAlert(title: "Invoice", errorMsg: error.debugDescription)
}
}
}
extension PaymentsVC: UITableViewDelegate, UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let emptyLabel = UILabel(frame: CGRect(x: 0, y: 0, width: self.view.bounds.size.width, height: self.view.bounds.size.height))
emptyLabel.text = ""
emptyLabel.textAlignment = NSTextAlignment.center
self.tableView.backgroundView = emptyLabel
if selectedListControl.selectedSegmentIndex == 0{
if let noOfPayments = viewModel.payments.value?.count{
return noOfPayments
}else{
emptyLabel.text = "No Payments"
self.tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
return 0
}
}else{
if let noOfInvoices = viewModel.invoices.value?.count{
return noOfInvoices
}else{
emptyLabel.text = "No Invoices"
self.tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
return 0
}
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let reuseCellIdentifier = "cellIdentifier"
var cell = tableView.dequeueReusableCell(withIdentifier: reuseCellIdentifier)
if (!(cell != nil)) {
cell = UITableViewCell(style: .subtitle, reuseIdentifier: reuseCellIdentifier)
}
cell?.textLabel?.numberOfLines = 0
cell?.detailTextLabel?.numberOfLines = 0
if selectedListControl.selectedSegmentIndex == 0{
if let payment = viewModel.payments.value?[indexPath.row]{
cell?.textLabel?.text = "Status: \(payment.status) \nAmount: \(payment.value) sat"
cell?.detailTextLabel?.text = "\nDate: \(payment.creationDate.getAsDate()) \nFee:\(payment.feeSat) \nPayment hash:\n\(payment.paymentRequest.description)"
}
}else{
if let invoice = viewModel.invoices.value?[indexPath.row]{
cell?.textLabel?.text = "Status: \(invoice.state) \nAmount: \(invoice.value) sat"
cell?.detailTextLabel?.text = "\nDate Created: \(invoice.creationDate.getAsDate()) \nMemo:\(invoice.memo) \nPayment request: \(invoice.paymentRequest)"
}
}
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if selectedListControl.selectedSegmentIndex == 0{
if let payment = viewModel.payments.value?[indexPath.row]{
UIPasteboard.general.string = payment.paymentRequest.description
}
}else{
if let invoice = viewModel.invoices.value?[indexPath.row]{
self.showAlert(title: "Invoice", address: invoice.paymentRequest)
}
}
}
}
extension PaymentsVC: UITextFieldDelegate{
/**
* Called when 'return' key pressed. return NO to ignore.
*/
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if !(invoiceAmount.text?.isEmpty ?? true){
generateInvoiceBtn.isHidden = false
}
textField.resignFirstResponder()
return true
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField == invoiceAmount{
let allowedCharacters = CharacterSet.decimalDigits
let characterSet = CharacterSet(charactersIn: string)
return allowedCharacters.isSuperset(of: characterSet)
}
return true
}
/**
* Called when the user click on the view (outside the UITextField).
*/
func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.view.endEditing(true)
}
}
extension PaymentsVC: UITextPasteDelegate {
func textPasteConfigurationSupporting(_ textPasteConfigurationSupporting: UITextPasteConfigurationSupporting, shouldAnimatePasteOf attributedString: NSAttributedString, to textRange: UITextRange) -> Bool {
return false
}
}
extension PaymentsVC: UITextViewDelegate{
func textViewDidBeginEditing(_ textView: UITextView) {
if textView.textColor == UIColor.lightGray {
textView.text = nil
textView.textColor = UIColor.black
}
}
func textViewDidEndEditing(_ textView: UITextView) {
if textView.text.isEmpty {
textView.text = "Input Address ..."
textView.textColor = UIColor.lightGray
}
}
func textViewDidChange(_ textView: UITextView) {
if(textView.text == UIPasteboard.general.string){
}
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
// Combine the textView text and the replacement text to
// create the updated text string
let currentText:String = textView.text
let updatedText = (currentText as NSString).replacingCharacters(in: range, with: text)
// If updated text view will be empty, add the placeholder
// and set the cursor to the beginning of the text view
if updatedText.isEmpty {
textView.text = "Input Address ..."
textView.textColor = UIColor.lightGray
textView.selectedTextRange = textView.textRange(from: textView.beginningOfDocument, to: textView.beginningOfDocument)
}
// Else if the text view's placeholder is showing and the
// length of the replacement string is greater than 0, set
// the text color to black then set its text to the
// replacement string
else if textView.textColor == UIColor.lightGray && !text.isEmpty {
textView.textColor = UIColor.black
textView.text = text
}else if text == "\n" {
textView.resignFirstResponder()
self.viewModel.getPaymentDetail(invoice: textView.text)
return false
}
// For every other case, the text should change with the usual
// behavior...
else {
return true
}
// ...otherwise return false since the updates have already
// been made
return false
}
func textViewDidChangeSelection(_ textView: UITextView) {
if self.view.window != nil {
if textView.textColor == UIColor.lightGray {
textView.selectedTextRange = textView.textRange(from: textView.beginningOfDocument, to: textView.beginningOfDocument)
}
}
}
}
extension PaymentsVC: QRCodeScanViewControllerDelegate{
// MARK: QRCodeScanViewControllerDelegate
/// Called when the camera scans a QR code
/// - Parameters:
/// - viewController: View controller that scanned the QR code
/// - value: String encoded in the QR code
func qrCodeScanViewController(_ viewController: QRCodeScanViewController, didScanQRCode value: String) {
// Dismiss the view controller
viewController.dismiss(animated: true) {
self.sendPaymentAddress.text = value
self.sendPaymentAddress.tintColor = UIColor.black
self.viewModel.getPaymentDetail(invoice: value)
}
}
}

View File

@ -0,0 +1,504 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_5" orientation="portrait" appearance="dark"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
<capability name="Image references" minToolsVersion="12.0"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="PaymentsVC" customModule="wallet" customModuleProvider="target">
<connections>
<outlet property="amountStepper" destination="T9i-3R-cri" id="acC-86-u4S"/>
<outlet property="cancelPayBtn" destination="U13-IO-hAk" id="hPn-DL-vGM"/>
<outlet property="cancelReceiveBtn" destination="ziL-bN-VuJ" id="kVP-kP-hzc"/>
<outlet property="estimateFeeValue" destination="Iwm-ze-Xdw" id="4AW-WP-rCe"/>
<outlet property="feeStackView" destination="iXB-vl-PMu" id="6nY-oa-oFO"/>
<outlet property="generateInvoiceBtn" destination="PBr-bz-1w7" id="oeA-6E-m9v"/>
<outlet property="invoiceAmount" destination="cEe-CT-RNM" id="PPN-LF-dkX"/>
<outlet property="invoiceComment" destination="cVl-JJ-kdK" id="kAE-jl-WAA"/>
<outlet property="localBalanceValue" destination="5XZ-kK-3vj" id="0kf-Sw-s3H"/>
<outlet property="memoLbl" destination="hpJ-ik-Uk2" id="X8G-aF-5to"/>
<outlet property="payBtn" destination="8yZ-fV-Z9Q" id="J5Q-dP-pBk"/>
<outlet property="paymentButtonsStack" destination="SEY-by-HAH" id="jx2-GO-5RK"/>
<outlet property="paymentElements" destination="L4r-Do-IUm" id="fdZ-gw-OuJ"/>
<outlet property="paymentInfoCreated" destination="biX-qT-Uvp" id="glg-CQ-rRM"/>
<outlet property="paymentInfoExpiry" destination="yvM-6G-jWp" id="Iz9-cq-N7D"/>
<outlet property="paymentInfoLbl" destination="Qwo-Y1-a24" id="swz-pb-L4o"/>
<outlet property="paymentInfoStack" destination="WGx-MS-QY4" id="Be1-Kg-pP3"/>
<outlet property="receiveStackView" destination="MyI-gR-AxB" id="Rsz-yN-qmb"/>
<outlet property="remoteBalanceValue" destination="5wG-S9-P0n" id="q2N-uP-XDu"/>
<outlet property="selectedListControl" destination="Vcc-bu-AMC" id="c0R-WA-Ihu"/>
<outlet property="sendPaymentAddress" destination="K52-8B-0Ky" id="5Wo-ft-rVC"/>
<outlet property="sendStackView" destination="VNJ-zr-pHr" id="wVH-2J-c9a"/>
<outlet property="tableView" destination="0jD-Yd-8Mg" id="YPu-rQ-Ksh"/>
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
<outlet property="walletBalanceValue" destination="7GV-G8-6RM" id="hFw-WK-gcd"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="Xai-Q3-vRS" userLabel="Payment Stack">
<rect key="frame" x="10" y="64" width="394" height="788"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="L4r-Do-IUm">
<rect key="frame" x="0.0" y="0.0" width="394" height="198"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="mgZ-Yn-C0m">
<rect key="frame" x="0.0" y="0.0" width="394" height="19.333333333333332"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Wallet Balance:" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8CK-SL-j6c">
<rect key="frame" x="0.0" y="0.0" width="321.33333333333331" height="19.333333333333332"/>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="7GV-G8-6RM">
<rect key="frame" x="331.33333333333331" y="0.0" width="12.666666666666686" height="19.333333333333332"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="20"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="sats" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9yF-Lj-HGL">
<rect key="frame" x="354" y="0.0" width="40" height="19.333333333333332"/>
<constraints>
<constraint firstAttribute="width" constant="40" id="Yst-ng-iXy"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="yhP-LX-kWu">
<rect key="frame" x="0.0" y="29.333333333333329" width="394" height="19.333333333333329"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Local Balance:" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3qv-zE-MGq">
<rect key="frame" x="0.0" y="0.0" width="321.33333333333331" height="19.333333333333332"/>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5XZ-kK-3vj">
<rect key="frame" x="331.33333333333331" y="0.0" width="12.666666666666686" height="19.333333333333332"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="20"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="sats" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="N5R-zX-pSx">
<rect key="frame" x="354" y="0.0" width="40" height="19.333333333333332"/>
<constraints>
<constraint firstAttribute="width" constant="40" id="WT3-Ht-Fwr"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="N6B-qA-M1m">
<rect key="frame" x="0.0" y="58.666666666666679" width="394" height="19.333333333333336"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Remote Balance:" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="xNf-Xs-Sca">
<rect key="frame" x="0.0" y="0.0" width="321.33333333333331" height="19.333333333333332"/>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5wG-S9-P0n">
<rect key="frame" x="331.33333333333331" y="0.0" width="12.666666666666686" height="19.333333333333332"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="20"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="sats" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4TF-14-eWd">
<rect key="frame" x="354" y="0.0" width="40" height="19.333333333333332"/>
<constraints>
<constraint firstAttribute="width" constant="40" id="nXc-92-f0h"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<stackView hidden="YES" opaque="NO" contentMode="scaleToFill" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="iXB-vl-PMu">
<rect key="frame" x="0.0" y="83" width="394" height="0.0"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Fee:" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8V9-WT-6A9">
<rect key="frame" x="0.0" y="0.0" width="321.33333333333331" height="0.0"/>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Iwm-ze-Xdw">
<rect key="frame" x="331.33333333333331" y="0.0" width="12.666666666666686" height="0.0"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="20"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="sats" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3xQ-a7-dyM">
<rect key="frame" x="354" y="0.0" width="40" height="0.0"/>
<constraints>
<constraint firstAttribute="width" constant="40" id="MVZ-TT-Mvc"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="SEY-by-HAH" userLabel="Payment Buttons">
<rect key="frame" x="0.0" y="88" width="394" height="40"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="gsg-XS-xUI">
<rect key="frame" x="0.0" y="0.0" width="192" height="40"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="E1b-s2-U3t"/>
</constraints>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Send" cornerStyle="medium">
<color key="baseForegroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="baseBackgroundColor" red="0.36654189230000001" green="0.68308699129999995" blue="0.86276882889999995" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
</buttonConfiguration>
<connections>
<action selector="didPressSend:" destination="-1" eventType="touchUpInside" id="pQB-sp-4HT"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1kb-AC-orN">
<rect key="frame" x="202" y="0.0" width="192" height="40"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Receive" cornerStyle="medium">
<color key="baseForegroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="baseBackgroundColor" red="0.36654189230000001" green="0.68308699129999995" blue="0.86276882889999995" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
</buttonConfiguration>
<connections>
<action selector="didPressReceive:" destination="-1" eventType="touchUpInside" id="KOA-VA-c0a"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</stackView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="RNs-xK-8tN">
<rect key="frame" x="0.0" y="138" width="394" height="60"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="HRH-3l-Ykt">
<rect key="frame" x="10" y="10" width="374" height="40"/>
<subviews>
<stackView hidden="YES" opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="VNJ-zr-pHr" userLabel="send">
<rect key="frame" x="0.0" y="0.0" width="285.66666666666669" height="210"/>
<subviews>
<textView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" keyboardDismissMode="interactive" textAlignment="natural" adjustsFontForContentSizeCategory="YES" translatesAutoresizingMaskIntoConstraints="NO" id="K52-8B-0Ky">
<rect key="frame" x="0.0" y="0.0" width="285.66666666666669" height="150"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="150" id="bFa-P4-AuL"/>
</constraints>
<color key="textColor" systemColor="labelColor"/>
<fontDescription key="fontDescription" type="system" weight="light" pointSize="12"/>
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" enablesReturnKeyAutomatically="YES" smartDashesType="no" smartQuotesType="no"/>
</textView>
<stackView hidden="YES" opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="top" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="WGx-MS-QY4">
<rect key="frame" x="0.0" y="155" width="285.66666666666669" height="15"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="Tac-1T-QSD">
<rect key="frame" x="0.0" y="0.0" width="131.66666666666666" height="0.0"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Amount:" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="67Y-cj-4UK">
<rect key="frame" x="0.0" y="0.0" width="70" height="0.0"/>
<constraints>
<constraint firstAttribute="width" constant="70" id="CZT-dH-IUx"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Qwo-Y1-a24">
<rect key="frame" x="80" y="0.0" width="12.666666666666671" height="0.0"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="20"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="sats" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Iqx-qF-g4z">
<rect key="frame" x="102.66666666666667" y="0.0" width="29.000000000000014" height="0.0"/>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="svR-IM-B0c">
<rect key="frame" x="0.0" y="5" width="120" height="0.0"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Memo:" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="57B-x0-587">
<rect key="frame" x="0.0" y="0.0" width="60" height="0.0"/>
<constraints>
<constraint firstAttribute="width" constant="60" id="uwf-X1-6X0"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hpJ-ik-Uk2">
<rect key="frame" x="70" y="0.0" width="50" height="0.0"/>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="HYH-Kg-BVn">
<rect key="frame" x="0.0" y="10" width="160" height="0.0"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Created at:" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0o5-97-tmh">
<rect key="frame" x="0.0" y="0.0" width="100" height="0.0"/>
<constraints>
<constraint firstAttribute="width" constant="100" id="lly-03-g64"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="biX-qT-Uvp">
<rect key="frame" x="110" y="0.0" width="50" height="0.0"/>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="18"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="aeg-eq-JkP">
<rect key="frame" x="0.0" y="15" width="160" height="0.0"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Expires at:" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dfn-1O-d7Q">
<rect key="frame" x="0.0" y="0.0" width="100" height="0.0"/>
<constraints>
<constraint firstAttribute="width" constant="100" id="cLy-eY-6cd"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="16"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yvM-6G-jWp">
<rect key="frame" x="110" y="0.0" width="50" height="0.0"/>
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="18"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="1Ve-gj-DTh">
<rect key="frame" x="0.0" y="160" width="285.66666666666669" height="50"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="K7J-kG-4Zh" userLabel="Info">
<rect key="frame" x="0.0" y="0.0" width="285.66666666666669" height="0.0"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<buttonConfiguration key="configuration" style="filled" title="Scan" cornerStyle="capsule">
<imageReference key="image" image="qrcode" catalog="system" symbolScale="medium"/>
<preferredSymbolConfiguration key="preferredSymbolConfigurationForImage" configurationType="pointSize" pointSize="20" scale="large" weight="semibold"/>
<color key="baseForegroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="baseBackgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</buttonConfiguration>
<connections>
<action selector="didPressScan:" destination="-1" eventType="touchUpInside" id="R4X-3z-pmw"/>
</connections>
</button>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="8yZ-fV-Z9Q">
<rect key="frame" x="0.0" y="5" width="285.66666666666669" height="0.0"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Pay" cornerStyle="medium">
<color key="baseForegroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="baseBackgroundColor" red="0.36654189230000001" green="0.68308699129999995" blue="0.86276882889999995" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
</buttonConfiguration>
<connections>
<action selector="didPressPay:" destination="-1" eventType="touchUpInside" id="Hn3-G1-qHq"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="U13-IO-hAk">
<rect key="frame" x="0.0" y="10" width="285.66666666666669" height="40"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="Fnb-yO-R5y"/>
</constraints>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Cancel" cornerStyle="medium">
<color key="baseForegroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="baseBackgroundColor" red="0.36654189230000001" green="0.68308699129999995" blue="0.86276882889999995" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
</buttonConfiguration>
<connections>
<action selector="didPressCancel:" destination="-1" eventType="touchUpInside" id="dXn-9n-thO"/>
</connections>
</button>
</subviews>
</stackView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</stackView>
<stackView hidden="YES" opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="MyI-gR-AxB" userLabel="receive">
<rect key="frame" x="0.0" y="0.0" width="285.66666666666669" height="45"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" distribution="equalCentering" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="z3t-KC-SNp">
<rect key="frame" x="0.0" y="0.0" width="285.66666666666669" height="25"/>
<subviews>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="0" borderStyle="roundedRect" placeholder="Amount" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="cEe-CT-RNM">
<rect key="frame" x="0.0" y="0.0" width="150" height="25"/>
<constraints>
<constraint firstAttribute="width" constant="150" id="1Pj-2G-wMB"/>
<constraint firstAttribute="height" constant="25" id="bKd-8V-HHN"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits"/>
</textField>
<stepper opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" wraps="YES" value="100" maximumValue="9.2233720368547758e+18" stepValue="100" translatesAutoresizingMaskIntoConstraints="NO" id="T9i-3R-cri">
<rect key="frame" x="155" y="0.0" width="94" height="25"/>
<connections>
<action selector="didUpdateStepper:" destination="-1" eventType="valueChanged" id="z5d-tw-ZMC"/>
</connections>
</stepper>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="sats" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="pAl-cD-IYY">
<rect key="frame" x="253.99999999999997" y="0.0" width="31.666666666666657" height="25"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Comment" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="cVl-JJ-kdK">
<rect key="frame" x="0.0" y="35" width="285.66666666666669" height="0.0"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits"/>
</textField>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="Cto-uA-T1L">
<rect key="frame" x="0.0" y="45" width="285.66666666666669" height="0.0"/>
<subviews>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="PBr-bz-1w7">
<rect key="frame" x="0.0" y="0.0" width="285.66666666666669" height="40"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="Z0b-Mk-QPp"/>
</constraints>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Generate" cornerStyle="medium">
<color key="baseForegroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="baseBackgroundColor" red="0.36654189230000001" green="0.68308699129999995" blue="0.86276882889999995" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
</buttonConfiguration>
<connections>
<action selector="didPressGenerateBtn:" destination="-1" eventType="touchUpInside" id="epK-9J-1ee"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ziL-bN-VuJ">
<rect key="frame" x="0.0" y="0.0" width="285.66666666666669" height="0.0"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Cancel" cornerStyle="medium">
<color key="baseForegroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="baseBackgroundColor" red="0.36654189230000001" green="0.68308699129999995" blue="0.86276882889999995" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
</buttonConfiguration>
<connections>
<action selector="didPressCancel:" destination="-1" eventType="touchUpInside" id="nO9-Jz-ets"/>
</connections>
</button>
</subviews>
</stackView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</stackView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="MyI-gR-AxB" firstAttribute="top" secondItem="VNJ-zr-pHr" secondAttribute="top" id="9lN-jD-HfN"/>
</constraints>
</stackView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="HRH-3l-Ykt" firstAttribute="top" secondItem="RNs-xK-8tN" secondAttribute="top" constant="10" id="Cl7-op-iJG"/>
<constraint firstAttribute="trailing" secondItem="HRH-3l-Ykt" secondAttribute="trailing" constant="10" id="JFP-9K-BgM"/>
<constraint firstItem="HRH-3l-Ykt" firstAttribute="leading" secondItem="RNs-xK-8tN" secondAttribute="leading" constant="10" id="Kym-PA-1F9"/>
<constraint firstAttribute="bottom" secondItem="HRH-3l-Ykt" secondAttribute="bottom" constant="10" id="eOV-lf-RI0"/>
</constraints>
</view>
</subviews>
</stackView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="lyu-T0-nGv" userLabel="List">
<rect key="frame" x="0.0" y="208" width="394" height="580"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="wtf-8Z-bdx" userLabel="List Stack">
<rect key="frame" x="0.0" y="0.0" width="394" height="580"/>
<subviews>
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="Vcc-bu-AMC">
<rect key="frame" x="0.0" y="0.0" width="394" height="41"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="sES-9u-W0X"/>
</constraints>
<segments>
<segment title="Payments"/>
<segment title="Invoices"/>
</segments>
<connections>
<action selector="didChangeSelection:" destination="-1" eventType="valueChanged" id="SHG-tw-x2o"/>
</connections>
</segmentedControl>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" style="insetGrouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" estimatedSectionHeaderHeight="-1" sectionFooterHeight="18" estimatedSectionFooterHeight="-1" translatesAutoresizingMaskIntoConstraints="NO" id="0jD-Yd-8Mg">
<rect key="frame" x="0.0" y="50" width="394" height="530"/>
</tableView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</stackView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="wtf-8Z-bdx" firstAttribute="leading" secondItem="lyu-T0-nGv" secondAttribute="leading" id="8SA-T0-q0T"/>
<constraint firstItem="wtf-8Z-bdx" firstAttribute="top" secondItem="lyu-T0-nGv" secondAttribute="top" id="alN-m4-3Nr"/>
<constraint firstAttribute="bottom" secondItem="wtf-8Z-bdx" secondAttribute="bottom" id="lCZ-4p-r9M"/>
<constraint firstAttribute="trailing" secondItem="wtf-8Z-bdx" secondAttribute="trailing" id="qwW-6L-a3y"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="lyu-T0-nGv" firstAttribute="top" secondItem="L4r-Do-IUm" secondAttribute="bottom" constant="10" id="dI9-C9-v9e"/>
</constraints>
</stackView>
</subviews>
<viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="Xai-Q3-vRS" firstAttribute="top" secondItem="fnl-2z-Ty3" secondAttribute="top" constant="20" id="0eZ-ap-g4i"/>
<constraint firstItem="fnl-2z-Ty3" firstAttribute="bottom" secondItem="Xai-Q3-vRS" secondAttribute="bottom" constant="10" id="S5g-7w-Mch"/>
<constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="Xai-Q3-vRS" secondAttribute="trailing" constant="10" id="bOe-13-CQQ"/>
<constraint firstItem="Xai-Q3-vRS" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" constant="10" id="vLe-6j-pRa"/>
</constraints>
<point key="canvasLocation" x="137.68115942028987" y="81.696428571428569"/>
</view>
</objects>
<resources>
<image name="qrcode" catalog="system" width="128" height="114"/>
<systemColor name="labelColor">
<color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>