319 lines
11 KiB
Swift
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)
|
||
|
}
|
||
|
}
|
||
|
}
|