@@ -3,6 +3,10 @@ import GRPC
33import RxSwift
44
55public class Kit {
6+ enum ArgumentError : Error {
7+ case wrongChannelPoint
8+ }
9+
610 private let lndNode : ILndNode
711 private let paymentsUpdatedSubject = PublishSubject < Void > ( )
812
@@ -28,19 +32,23 @@ public class Kit {
2832 }
2933 public var channelBalanceObservable : Observable < Lnrpc_ChannelBalanceResponse > {
3034 Observable
31- . merge ( [
32- paymentsObservable,
33- invoicesObservable. filter { $0. state == . settled } . map { _ in Void ( ) }
34- ] )
35- . flatMap { [ weak self] _ in
36- self ? . channelBalanceSingle. asObservable ( ) ?? Observable . empty ( )
37- }
35+ . merge ( [
36+ paymentsObservable,
37+ invoicesObservable. filter {
38+ $0. state == . settled
39+ } . map { _ in
40+ Void ( )
41+ }
42+ ] )
43+ . flatMap { [ weak self] _ in
44+ self ? . channelBalanceSingle. asObservable ( ) ?? Observable . empty ( )
45+ }
3846 }
39-
47+
4048 fileprivate init ( lndNode: ILndNode ) {
4149 self . lndNode = lndNode
4250 }
43-
51+
4452 public var walletBalanceSingle : Single < Lnrpc_WalletBalanceResponse > {
4553 lndNode. walletBalanceSingle
4654 }
@@ -64,96 +72,175 @@ public class Kit {
6472 public var pendingChannelsSingle : Single < Lnrpc_PendingChannelsResponse > {
6573 lndNode. pendingChannelsSingle
6674 }
67-
75+
6876 public var paymentsSingle : Single < Lnrpc_ListPaymentsResponse > {
6977 lndNode. paymentsSingle
7078 }
79+
80+ public var transactionsSingle : Single < Lnrpc_TransactionDetails > {
81+ lndNode. transactionsSingle
82+ }
83+
84+ public func invoicesSingle( pendingOnly: Bool = false , offset: UInt64 = 0 , limit: UInt64 = 1000 , reversed: Bool = false ) -> Single < Lnrpc_ListInvoiceResponse > {
85+ var request = Lnrpc_ListInvoiceRequest ( )
86+ request. pendingOnly = pendingOnly
87+ request. indexOffset = offset
88+ request. numMaxInvoices = limit
89+ request. reversed = reversed
7190
72- public func invoicesSingle( pending_only: Bool = false , offset: UInt64 = 0 , limit: UInt64 = 1000 , reversed: Bool = false ) -> Single < Lnrpc_ListInvoiceResponse > {
73- lndNode. invoicesSingle ( pendingOnly: pending_only, offset: offset, limit: limit, reversed: reversed)
91+ return lndNode. invoicesSingle ( request: request)
7492 }
75-
93+
7694 public func paySingle( invoice: String ) -> Single < Lnrpc_SendResponse > {
77- return lndNode. paySingle ( invoice: invoice)
78- . do ( onSuccess: { [ weak self] in
79- if $0. paymentError. isEmpty {
80- self ? . paymentsUpdatedSubject. onNext ( Void ( ) )
81- }
82- } )
95+ var request = Lnrpc_SendRequest ( )
96+ request. paymentRequest = invoice
97+
98+ return lndNode. paySingle ( request: request)
99+ . do ( onSuccess: { [ weak self] in
100+ if $0. paymentError. isEmpty {
101+ self ? . paymentsUpdatedSubject. onNext ( Void ( ) )
102+ }
103+ } )
83104 }
84105
85106 public func addInvoiceSingle( amount: Int64 , memo: String ) -> Single < Lnrpc_AddInvoiceResponse > {
86- lndNode. addInvoiceSingle ( amount: amount, memo: memo)
107+ var invoice = Lnrpc_Invoice ( )
108+ invoice. value = amount
109+ invoice. memo = memo
110+
111+ return lndNode. addInvoiceSingle ( invoice: invoice)
87112 }
88113
89114 public func unlockWalletSingle( password: Data ) -> Single < Void > {
90- lndNode. unlockWalletSingle ( password: password)
115+ var request = Lnrpc_UnlockWalletRequest ( )
116+ request. walletPassword = password
117+
118+ return lndNode. unlockWalletSingle ( request: request)
91119 }
92-
120+
93121 public func decodeSingle( paymentRequest: String ) -> Single < Lnrpc_PayReq > {
94- lndNode. decodeSingle ( paymentRequest: paymentRequest)
122+ var request = Lnrpc_PayReqString ( )
123+ request. payReq = paymentRequest
124+
125+ return lndNode. decodeSingle ( paymentRequest: request)
95126 }
96127
97128 public func openChannelSingle( nodePubKey: Data , amount: Int64 , nodeAddress: String ) -> Observable < Lnrpc_OpenStatusUpdate > {
98- lndNode. connectSingle ( nodeAddress: nodeAddress, nodePubKey: nodePubKey. hex)
99- . map { _ in Void ( ) }
100- . catchError { error -> Single < Void > in
101- if let grpcStatus = error as? GRPC . GRPCStatus , let message = grpcStatus. message,
102- message. contains ( " already connected to peer " ) {
103- return Single . just ( Void ( ) )
104- } else {
105- return Single . error ( error)
129+ var openChannelRequest = Lnrpc_OpenChannelRequest ( )
130+ openChannelRequest. nodePubkey = nodePubKey
131+ openChannelRequest. satPerByte = 2 // todo: extract as param
132+ openChannelRequest. localFundingAmount = amount
133+
134+ var lightningAddress = Lnrpc_LightningAddress ( )
135+ lightningAddress. pubkey = nodePubKey. hex
136+ lightningAddress. host = nodeAddress
137+
138+ var connectPeersRequest = Lnrpc_ConnectPeerRequest ( )
139+ connectPeersRequest. addr = lightningAddress
140+
141+ return lndNode. connectSingle ( request: connectPeersRequest)
142+ . map { _ in
143+ Void ( )
106144 }
107- }
108- . asObservable ( )
109- . flatMap { [ weak self] _ -> Observable < Lnrpc_OpenStatusUpdate > in
110- guard let kit = self else {
111- return Observable . empty ( )
145+ . catchError { error -> Single < Void > in
146+ if let grpcStatus = error as? GRPC . GRPCStatus , let message = grpcStatus. message,
147+ message. contains ( " already connected to peer " ) {
148+ return Single . just ( Void ( ) )
149+ } else {
150+ return Single . error ( error)
151+ }
152+ }
153+ . asObservable ( )
154+ . flatMap { [ weak self] _ -> Observable < Lnrpc_OpenStatusUpdate > in
155+ guard let kit = self else {
156+ return Observable . empty ( )
157+ }
158+
159+ return kit. lndNode. openChannelSingle ( request: openChannelRequest)
112160 }
113-
114- return kit. lndNode. openChannelSingle ( nodePubKey: nodePubKey, amount: amount)
115- }
116161 }
117162
118163 public func closeChannelSingle( channelPoint: String , forceClose: Bool ) throws -> Observable < Lnrpc_CloseStatusUpdate > {
119- try lndNode. closeChannelSingle ( channelPoint: channelPoint, forceClose: forceClose)
164+ let channelPointParts = channelPoint. split ( separator: " : " )
165+
166+ guard channelPointParts. count == 0 , let outputIndex = UInt32 ( String ( channelPointParts [ 1 ] ) ) else {
167+ throw ArgumentError . wrongChannelPoint
168+ }
169+
170+ var channelPoint = Lnrpc_ChannelPoint ( )
171+ channelPoint. fundingTxidStr = String ( channelPointParts [ 0 ] )
172+ channelPoint. outputIndex = outputIndex
173+
174+ var request = Lnrpc_CloseChannelRequest ( )
175+ request. channelPoint = channelPoint
176+ request. satPerByte = 2 // todo: extract as param
177+ request. force = forceClose
178+
179+ return try lndNode. closeChannelSingle ( request: request)
120180 }
121181
122182 private func retryWhenStatusIsSyncingOrRunning< T> ( _ observable: Observable < T > ) -> Observable < T > {
123183 observable. retryWhen { [ weak self] errorObservable -> Observable < ( Error , NodeStatus ) > in
124184 guard let kit = self else {
125185 return . empty( )
126186 }
127-
128- return Observable . zip ( errorObservable, kit. statusObservable. filter { $0 == . syncing || $0 == . running } )
187+
188+ return Observable . zip ( errorObservable, kit. statusObservable. filter {
189+ $0 == . syncing || $0 == . running
190+ } )
129191 }
130192 }
131193}
132194
133195public extension Kit {
134196 static var lightningKitLocalLnd : Kit ? = nil
135-
197+
136198 static func validateRemoteConnection( rpcCredentials: RpcCredentials ) -> Single < Void > {
137199 do {
138200 let remoteLndNode = try RemoteLnd ( rpcCredentials: rpcCredentials)
139-
201+
140202 return remoteLndNode. validateAsync ( )
141203 } catch {
142204 return Single . error ( error)
143205 }
144206 }
145207
208+ static func local( credentials: LocalNodeCredentials ) -> Kit {
209+ if let kit = lightningKitLocalLnd {
210+ return kit
211+ }
212+
213+ let localLnd = LocalLnd ( filesDir: credentials. lndDirPath)
214+ localLnd. startAndUnlock ( password: credentials. password)
215+
216+ let kit = Kit ( lndNode: localLnd)
217+ lightningKitLocalLnd = kit
218+
219+ return kit
220+ }
221+
146222 static func createLocal( credentials: LocalNodeCredentials ) -> Single < [ String ] > {
147- let localLnd = LocalLnd ( credentials : credentials)
223+ let localLnd = LocalLnd ( filesDir : credentials. lndDirPath )
148224 lightningKitLocalLnd = Kit ( lndNode: localLnd)
149225
150- return localLnd. start ( ) . flatMap { localLnd. createWallet ( password: credentials. password) }
226+ return localLnd. start ( ) . flatMap {
227+ localLnd. createWalletSingle ( password: credentials. password)
228+ }
229+ }
230+
231+ static func restoreLocal( words: [ String ] , credentials: LocalNodeCredentials ) -> Single < Void > {
232+ let localLnd = LocalLnd ( filesDir: credentials. lndDirPath)
233+ lightningKitLocalLnd = Kit ( lndNode: localLnd)
234+
235+ return localLnd. start ( ) . flatMap {
236+ localLnd. restoreWalletSingle ( words: words, password: credentials. password)
237+ }
151238 }
152239
153240 static func remote( rpcCredentials: RpcCredentials ) throws -> Kit {
154241 let remoteLndNode = try RemoteLnd ( rpcCredentials: rpcCredentials)
155242 remoteLndNode. scheduleStatusUpdates ( )
156-
243+
157244 return Kit ( lndNode: remoteLndNode)
158245 }
159246}
0 commit comments