lnd-demo-app/wallet/ViewModels/ViewModel.swift
2023-06-08 09:36:06 +03:00

319 lines
11 KiB
Swift

//
// ViewModel.swift
// wallet
//
// Created by Jason on 8/23/20.
// Copyright © 2020 Jason. All rights reserved.
//
import Foundation
struct WalletBalance{
let total: Int
let confirmed: Int
let unconfirmed: Int
}
class ViewModel {
//TODO: Hardcoded values. Change these later.mailto:0245fc5e867abb5b83ead35b50dc5013dd358b9f3eb48c02f5e1cc9fc675039359@uld2jqbrrwsowhxobvxlrl6j7qc2rmccsmnnf6ba4jepkugxqkyohvad.onion:9735
private var nodePubKey = try! NodePublicKey("0245fc5e867abb5b83ead35b50dc5013dd358b9f3eb48c02f5e1cc9fc675039359")
private var hostAddress = "bmadesign.go.ro"
private var hostPort: UInt = 9735
private let closeAddress = "tb1qylxttvn7wm7vsc2j36cjvmpl7nykcrzqkz6avl"
let newAddress = Observable<String>()
private let exampleRepo = ExampleRepository()
let isLoading = Observable<Bool>()
let lightningRepo = LightningRepository()
let walletWipe = Observable<Void>()
let walletBalance = Observable<WalletBalance>()
let channelBalance = Observable<Int>()
let lndInfo = Observable<Lnrpc_GetInfoResponse>()
let channels = Observable<[Lnrpc_Channel]>()
let closedChannels = Observable<[Lnrpc_ChannelCloseSummary]>()
let pendingChannels = Observable<Lnrpc_PendingChannelsResponse>()
let peers = Observable<[Lnrpc_Peer]>()
let invoices = Observable<[Lnrpc_Invoice]>()
let payments = Observable<[Lnrpc_Payment]>()
required init() {
// Empty
}
//MARK: - LND
func load() {
isLoading.value = true
// This is an example of a fetch to some data provider (i.e. an http api or something else)
// and where you can place the observed response
exampleRepo.getRandomInt(
onSuccess: { [weak self] someInt in
self?.isLoading.value = false
},
onFailure: { [weak self] error in
self?.isLoading.value = false
})
}
func getInfo() {
self.isLoading.value = true
lightningRepo.getInfo { [weak self] (res) in
self?.isLoading.value = false
self?.lndInfo.value = res
debugPrint("Response get Info", res)
} onFailure: { [weak self] (error) in
self?.isLoading.value = false
}
}
func getNewAddress() {
self.isLoading.value = true
lightningRepo.getNewAddress(
onSuccess: { [weak self] address in
self?.isLoading.value = false
self?.newAddress.value = address
debugPrint("Address :", address)
},
onFailure: { [weak self] error in
self?.isLoading.value = false
debugPrint(error?.localizedDescription as Any)
})
}
//MARK: - Wallet
func createWallet(password: String) {
self.isLoading.value = true
lightningRepo.createWallet(
password: password,
onSuccess: { [weak self] seed in
self?.isLoading.value = false
},
onFailure: { [weak self] error in
self?.isLoading.value = false
})
}
func unlockWallet(password: String) {
self.isLoading.value = true
lightningRepo.unlockWallet(
password: password,
onSuccess: { [weak self] in
self?.isLoading.value = false
self?.getInfo()
self?.getWalletBalance()
},
onFailure: { [weak self] error in
self?.isLoading.value = false
debugPrint(error?.localizedDescription as Any)
})
}
func getWalletBalance() {
lightningRepo.getWalletBalance(
onSuccess: { [weak self] (total, confirmed, unconfirmed) in
self?.walletBalance.value = WalletBalance(total: Int(total), confirmed: Int(confirmed), unconfirmed: Int(unconfirmed))
},
onFailure: { error in
debugPrint("Wallet balance error", error?.localizedDescription as Any) // TODO: Change to error
})
}
func wipeWallet() {
self.isLoading.value = true
lightningRepo.wipeWallet(
onSuccess: { [weak self] in
self?.isLoading.value = false
self?.walletWipe.value = ()
},
onFailure: { [weak self] error in
self?.isLoading.value = false
debugPrint(error?.localizedDescription as Any)
})
}
//MARK: - Channels
func openChannel(nodePubKey: String, hostAddress: String, port: UInt, pushSat: Int, localFunding: Int, onSuccess: @escaping (String) -> Void, onFailure: @escaping (Error?) -> Void) {
debugPrint("Node pub key", nodePubKey, hostAddress, port, pushSat, localFunding)
lightningRepo.openChannel(
localFunding: Int64(localFunding),
pushSat: Int64(pushSat),
host: hostAddress,
port: port,
nodePubKey: try! NodePublicKey(nodePubKey),
closeAddress: nil,
onSuccess: { message in
onSuccess(message)
},
onFailure: { error in
onFailure(error)
})
}
func closeChannel(channel:Lnrpc_Channel, onSuccess: @escaping (String) -> Void, onFailure: @escaping (Error?) -> Void) {
lightningRepo.closeChannel(channel: channel) { response in
self.listChannels()
debugPrint("Response", response)
} onFailure: { error in
debugPrint("Error", error)
}
}
func listChannels() {
self.isLoading.value = true
lightningRepo.listChannels(onSuccess: { [weak self] (response) in
self?.isLoading.value = false
self?.channels.value = response.channels.sorted{$0.uptime > $1.uptime}
debugPrint("Channels response ", response)
}) { [weak self] (error) in
self?.isLoading.value = false
}
}
func listClosedChannels() {
self.isLoading.value = true
lightningRepo.listClosedChannels(onSuccess: { [weak self] (response) in
self?.isLoading.value = false
self?.closedChannels.value = response.channels
debugPrint("Channels response ", response)
}) { [weak self] (error) in
self?.isLoading.value = false
}
}
func listPendingChannels() {
self.isLoading.value = true
lightningRepo.listPendingChannels(onSuccess: { [weak self] (response) in
self?.isLoading.value = false
self?.pendingChannels.value = response
debugPrint("Channels response ", response)
}) { [weak self] (error) in
self?.isLoading.value = false
}
}
func getChannelBalance(){
lightningRepo.getLightningChannelBalance { balance in
self.channelBalance.value = Int(balance.balance)
debugPrint("Channel balance", balance)
} onFailure: { error in
debugPrint("Channel balance error", error.debugDescription)
}
}
func getChannelInfo(id: UInt64, onSuccess: @escaping (Lnrpc_ChannelEdge) -> Void, onFailure: @escaping (Error?) -> Void) {
lightningRepo.getChannelInfo(id: id) { (channel) in
onSuccess(channel)
} onFailure: { (error) in
onFailure(error)
}
}
//MARK: - Peers
func listPeers(){
lightningRepo.listPeers { res in
debugPrint("Listing peers response", res.peers)
self.peers.value = res.peers
if res.peers.count > 0 {
if let pubKey = res.peers.first?.pubKey {
self.nodePubKey = try! NodePublicKey(pubKey)
if let address = res.peers.first?.address{
let addressArray = address.split(separator: ":")
self.hostAddress = addressArray[0].description
self.hostPort = UInt(addressArray[1].description) ?? 9735
}
}
}
} onFailure: { error in
debugPrint("Listing peers error", error ?? "")
}
}
//MARK: - Payments
func listPayments(){
self.isLoading.value = true
lightningRepo.listPayments { [weak self] (response) in
self?.isLoading.value = false
debugPrint("Response", response.payments)
self?.payments.value = response.payments.sorted{$0.creationDate > $1.creationDate}
} onFailure: { error in
debugPrint("Listing payments error", error ?? "")
self.isLoading.value = false
debugPrint(error?.localizedDescription as Any)
}
}
func getPaymentInfo(invoice: String, onSuccess: @escaping (Lnrpc_PayReq) -> Void, onFailure: @escaping (Error?) -> Void) {
lightningRepo.getPaymentInfo(paymentRequest: invoice, onSuccess: {onSuccess($0)}, onFailure: {onFailure($0)})
}
//MARK: - Invoices
func estimateFee(address: String, amount: Int, onSuccess: @escaping (String) -> Void, onFailure: @escaping (Error?) -> Void) {
lightningRepo.estimateFee(address: address, amount: Int64(amount)) { response in
debugPrint("Fee estimator response", response)
} onFailure: { error in
debugPrint("Fee estimator error", error.debugDescription)
}
}
func feeReport(onSuccess: @escaping (String) -> Void, onFailure: @escaping (Error?) -> Void) {
lightningRepo.feeReport() { response in
debugPrint("Fee report response", response)
} onFailure: { error in
debugPrint("Fee report error", error.debugDescription)
}
}
func createInvoice(amount: Int, comment: String, onSuccess: @escaping (String) -> Void, onFailure: @escaping (Error?) -> Void) {
self.isLoading.value = true
lightningRepo.createInvoice(amount: amount, memo: comment, onSuccess: { (response) in
self.isLoading.value = false
onSuccess(response.paymentRequest)
},onFailure: { error in
self.isLoading.value = false
onFailure(error)
})
}
func payInvoice(invoice: String, onSuccess: @escaping (Lnrpc_SendResponse) -> Void, onFailure: @escaping (Error?) -> Void) {
self.isLoading.value = true
lightningRepo.pay(paymentRequest: invoice, onSuccess: { [weak self] (response) in
self?.isLoading.value = false
onSuccess(response)
},onFailure: { [weak self] error in
self?.isLoading.value = false
debugPrint(error?.localizedDescription as Any)
onFailure(error)
})
}
func listInvoices(){
self.isLoading.value = true
lightningRepo.listInvoices(onSuccess: { [weak self] (response) in
self?.isLoading.value = false
debugPrint("Response", response.invoices)
self?.invoices.value = response.invoices.sorted{$0.creationDate > $1.creationDate}
}) { [weak self] (error) in
self?.isLoading.value = false
debugPrint(error?.localizedDescription as Any)
}
}
}