Skip to content

Commit ee34672

Browse files
committed
Refactor Kit initialization
1 parent 8eaea68 commit ee34672

File tree

9 files changed

+118
-107
lines changed

9 files changed

+118
-107
lines changed

LightningKit.xcodeproj/project.pbxproj

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
/* Begin PBXBuildFile section */
1010
2FA5DC8A66918200D42EA1EE /* MessageResponseStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FA5D6FACBD18084B3922C1B /* MessageResponseStream.swift */; };
1111
D059940C2403C9DE0096AC17 /* Lndmobile.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D059940B2403C9DE0096AC17 /* Lndmobile.framework */; };
12+
D09B6F4F240CD100009A883F /* GRPC in Frameworks */ = {isa = PBXBuildFile; productRef = D3A733C923FA80A2005DAC30 /* GRPC */; };
13+
D09B6F56240D3332009A883F /* RpcReadyCallback.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09B6F55240D3332009A883F /* RpcReadyCallback.swift */; };
1214
D3A7339423FA7D94005DAC30 /* LightningKit.h in Headers */ = {isa = PBXBuildFile; fileRef = D3A7339223FA7D94005DAC30 /* LightningKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
1315
D3A733B123FA7E98005DAC30 /* RemoteLnd.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3A7339B23FA7E98005DAC30 /* RemoteLnd.swift */; };
1416
D3A733B223FA7E98005DAC30 /* WalletUnlocker.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3A7339C23FA7E98005DAC30 /* WalletUnlocker.swift */; };
@@ -36,6 +38,8 @@
3638
2FA5D6FACBD18084B3922C1B /* MessageResponseStream.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageResponseStream.swift; sourceTree = "<group>"; };
3739
D059940B2403C9DE0096AC17 /* Lndmobile.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Lndmobile.framework; path = Carthage/Build/iOS/Lndmobile.framework; sourceTree = SOURCE_ROOT; };
3840
D05C723F70B6969736B4E735 /* Pods_LightningKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LightningKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
41+
D09B6F50240CD306009A883F /* RxBlocking.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = RxBlocking.framework; sourceTree = BUILT_PRODUCTS_DIR; };
42+
D09B6F55240D3332009A883F /* RpcReadyCallback.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RpcReadyCallback.swift; sourceTree = "<group>"; };
3943
D3A7338F23FA7D94005DAC30 /* LightningKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LightningKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
4044
D3A7339223FA7D94005DAC30 /* LightningKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LightningKit.h; sourceTree = "<group>"; };
4145
D3A7339323FA7D94005DAC30 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -67,6 +71,7 @@
6771
files = (
6872
D059940C2403C9DE0096AC17 /* Lndmobile.framework in Frameworks */,
6973
E989B9E19F21A2518A31A210 /* Pods_LightningKit.framework in Frameworks */,
74+
D09B6F4F240CD100009A883F /* GRPC in Frameworks */,
7075
);
7176
runOnlyForDeploymentPostprocessing = 0;
7277
};
@@ -161,17 +166,19 @@
161166
D3A733AC23FA7E98005DAC30 /* LndMobileCallbacks */ = {
162167
isa = PBXGroup;
163168
children = (
169+
D3A733AE23FA7E98005DAC30 /* LndMobileCallbackError.swift */,
164170
D3A733AF23FA7E98005DAC30 /* VoidResponseCallback.swift */,
165171
D3A733AD23FA7E98005DAC30 /* MessageResponseCallback.swift */,
166172
2FA5D6FACBD18084B3922C1B /* MessageResponseStream.swift */,
167-
D3A733AE23FA7E98005DAC30 /* LndMobileCallbackError.swift */,
173+
D09B6F55240D3332009A883F /* RpcReadyCallback.swift */,
168174
);
169175
path = LndMobileCallbacks;
170176
sourceTree = "<group>";
171177
};
172178
D3A733C823FA80A2005DAC30 /* Frameworks */ = {
173179
isa = PBXGroup;
174180
children = (
181+
D09B6F50240CD306009A883F /* RxBlocking.framework */,
175182
D05C723F70B6969736B4E735 /* Pods_LightningKit.framework */,
176183
);
177184
name = Frameworks;
@@ -207,7 +214,7 @@
207214
);
208215
name = LightningKit;
209216
packageProductDependencies = (
210-
D3A733C923FA80A2005DAC30 /* XCSwiftPackageProductDependency */,
217+
D3A733C923FA80A2005DAC30 /* GRPC */,
211218
);
212219
productName = LightningKit;
213220
productReference = D3A7338F23FA7D94005DAC30 /* LightningKit.framework */;
@@ -238,7 +245,7 @@
238245
);
239246
mainGroup = D3A7338523FA7D94005DAC30;
240247
packageReferences = (
241-
D3A733C523FA7FD1005DAC30 /* XCRemoteSwiftPackageReference */,
248+
D3A733C523FA7FD1005DAC30 /* XCRemoteSwiftPackageReference "grpc-swift" */,
242249
);
243250
productRefGroup = D3A7339023FA7D94005DAC30 /* Products */;
244251
projectDirPath = "";
@@ -293,6 +300,7 @@
293300
D3A733B723FA7E98005DAC30 /* rpc.pb.swift in Sources */,
294301
D3A733B423FA7E98005DAC30 /* ConnectivityManager.swift in Sources */,
295302
D3A733BC23FA7E98005DAC30 /* FileManager.swift in Sources */,
303+
D09B6F56240D3332009A883F /* RpcReadyCallback.swift in Sources */,
296304
D3A733C023FA7E98005DAC30 /* LndMobileCallbackError.swift in Sources */,
297305
D3A733B923FA7E98005DAC30 /* RpcCredentials.swift in Sources */,
298306
D3A733BB23FA7E98005DAC30 /* Data.swift in Sources */,
@@ -451,7 +459,6 @@
451459
"$(PROJECT_DIR)/Carthage/Build/iOS",
452460
);
453461
INFOPLIST_FILE = LightningKit/Info.plist;
454-
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
455462
LD_RUNPATH_SEARCH_PATHS = (
456463
"$(inherited)",
457464
"@executable_path/Frameworks",
@@ -484,7 +491,6 @@
484491
"$(PROJECT_DIR)/Carthage/Build/iOS",
485492
);
486493
INFOPLIST_FILE = LightningKit/Info.plist;
487-
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
488494
LD_RUNPATH_SEARCH_PATHS = (
489495
"$(inherited)",
490496
"@executable_path/Frameworks",
@@ -523,7 +529,7 @@
523529
/* End XCConfigurationList section */
524530

525531
/* Begin XCRemoteSwiftPackageReference section */
526-
D3A733C523FA7FD1005DAC30 /* XCRemoteSwiftPackageReference */ = {
532+
D3A733C523FA7FD1005DAC30 /* XCRemoteSwiftPackageReference "grpc-swift" */ = {
527533
isa = XCRemoteSwiftPackageReference;
528534
repositoryURL = "git@github.com:grpc/grpc-swift.git";
529535
requirement = {
@@ -534,9 +540,9 @@
534540
/* End XCRemoteSwiftPackageReference section */
535541

536542
/* Begin XCSwiftPackageProductDependency section */
537-
D3A733C923FA80A2005DAC30 /* XCSwiftPackageProductDependency */ = {
543+
D3A733C923FA80A2005DAC30 /* GRPC */ = {
538544
isa = XCSwiftPackageProductDependency;
539-
package = D3A733C523FA7FD1005DAC30 /* XCRemoteSwiftPackageReference */;
545+
package = D3A733C523FA7FD1005DAC30 /* XCRemoteSwiftPackageReference "grpc-swift" */;
540546
productName = GRPC;
541547
};
542548
/* End XCSwiftPackageProductDependency section */

LightningKit/ILndNode.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ protocol ILndNode {
1818
var pendingChannelsSingle: Single<Lnrpc_PendingChannelsResponse> { get }
1919
var paymentsSingle: Single<Lnrpc_ListPaymentsResponse> { get }
2020
var transactionsSingle: Single<Lnrpc_TransactionDetails> { get }
21+
var newSeedSingle: Single<Lnrpc_GenSeedResponse> { get }
2122

2223
func invoicesSingle(request: Lnrpc_ListInvoiceRequest) -> Single<Lnrpc_ListInvoiceResponse>
2324
func paySingle(request: Lnrpc_SendRequest) -> Single<Lnrpc_SendResponse>
@@ -27,4 +28,6 @@ protocol ILndNode {
2728
func openChannelSingle(request: Lnrpc_OpenChannelRequest) -> Observable<Lnrpc_OpenStatusUpdate>
2829
func closeChannelSingle(request: Lnrpc_CloseChannelRequest) throws -> Observable<Lnrpc_CloseStatusUpdate>
2930
func connectSingle(request: Lnrpc_ConnectPeerRequest) -> Single<Lnrpc_ConnectPeerResponse>
31+
32+
func initWalletSingle(request: Lnrpc_InitWalletRequest) -> Single<Void>
3033
}

LightningKit/Kit.swift

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ public class Kit {
8282
lndNode.transactionsSingle
8383
}
8484

85+
public var newSeedSingle: Single<Lnrpc_GenSeedResponse> {
86+
lndNode.newSeedSingle
87+
}
88+
8589
public func invoicesSingle(pendingOnly: Bool = false, offset: UInt64 = 0, limit: UInt64 = 1000, reversed: Bool = false) -> Single<Lnrpc_ListInvoiceResponse> {
8690
var request = Lnrpc_ListInvoiceRequest()
8791
request.pendingOnly = pendingOnly
@@ -112,13 +116,20 @@ public class Kit {
112116
return lndNode.addInvoiceSingle(invoice: invoice)
113117
}
114118

115-
public func unlockWalletSingle(password: Data) -> Single<Void> {
119+
public func unlockWalletSingle(password: String) -> Single<Void> {
116120
var request = Lnrpc_UnlockWalletRequest()
117-
request.walletPassword = password
118-
121+
request.walletPassword = Data(Array(password.utf8))
122+
119123
return lndNode.unlockWalletSingle(request: request)
120124
}
121-
125+
126+
public func unlockWallet(password: String) throws {
127+
var request = Lnrpc_UnlockWalletRequest()
128+
request.walletPassword = Data(Array(password.utf8))
129+
130+
_ = try lndNode.unlockWalletSingle(request: request).toBlocking().first()
131+
}
132+
122133
public func decodeSingle(paymentRequest: String) -> Single<Lnrpc_PayReq> {
123134
var request = Lnrpc_PayReqString()
124135
request.payReq = paymentRequest
@@ -180,34 +191,13 @@ public class Kit {
180191
return try lndNode.closeChannelSingle(request: request)
181192
}
182193

183-
// LocalLnd methods
184-
185-
public func start(password: String) {
186-
guard let localNode = lndNode as? LocalLnd else {
187-
return
188-
}
189-
190-
localNode.startAndUnlock(password: password)
191-
}
192-
193-
public func create(password: String) -> Single<[String]> {
194-
guard let localNode = lndNode as? LocalLnd else {
195-
return Single.error(KitErrors.cannotInitRemoteNode)
196-
}
194+
public func initWalletSingle(words: [String], password: String, recoveryWindow: Int32 = 100) -> Single<Void> {
195+
var request = Lnrpc_InitWalletRequest()
196+
request.cipherSeedMnemonic = words
197+
request.walletPassword = Data(Array(password.utf8))
198+
request.recoveryWindow = recoveryWindow
197199

198-
return localNode.start().flatMap {
199-
localNode.createWalletSingle(password: password)
200-
}
201-
}
202-
203-
public func restore(words: [String], password: String) -> Single<Void> {
204-
guard let localNode = lndNode as? LocalLnd else {
205-
return Single.error(KitErrors.cannotInitRemoteNode)
206-
}
207-
208-
return localNode.start().flatMap {
209-
localNode.restoreWalletSingle(words: words, password: password)
210-
}
200+
return lndNode.initWalletSingle(request: request)
211201
}
212202

213203
// Private methods
@@ -244,8 +234,15 @@ public extension Kit {
244234
}
245235

246236
static func local() throws -> Kit {
247-
let localLnd = LocalLnd(filesDir: try FileManager.default.walletDirectory().path)
237+
let localLnd = try LocalLnd(filesDir: try FileManager.default.walletDirectory().path)
248238

249239
return Kit(lndNode: localLnd)
250240
}
241+
242+
static func clearLocalNodeData() throws {
243+
let fileManager = FileManager.default
244+
let lndDirectoryPath = try fileManager.walletDirectory().path
245+
246+
try fileManager.removeItem(atPath: lndDirectoryPath)
247+
}
251248
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import Lndmobile
2+
3+
class RpcReadyCallback: NSObject, LndmobileCallbackProtocol {
4+
private weak var delegate: RpcReadyCallbackDelegate?
5+
6+
init(_ delegate: RpcReadyCallbackDelegate?) {
7+
self.delegate = delegate
8+
}
9+
10+
func onError(_ error: Error?) {
11+
delegate?.RpcServerStartFailed(error: error ?? LndMobileCallbackError.unknownError)
12+
}
13+
14+
func onResponse(_ response: Data?) {
15+
delegate?.rpcReady()
16+
}
17+
}
18+
19+
protocol RpcReadyCallbackDelegate: AnyObject {
20+
func RpcServerStartFailed(error: Error)
21+
func rpcReady()
22+
}

LightningKit/Local/LocalLnd.swift

Lines changed: 29 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Lndmobile
22
import RxSwift
3+
import RxBlocking
34
import SwiftProtobuf
45

56
class LocalLnd: ILndNode {
@@ -116,23 +117,32 @@ class LocalLnd: ILndNode {
116117
var transactionsSingle: Single<Lnrpc_TransactionDetails> {
117118
Single.create { emitter in
118119
LndmobileGetTransactions(try! Lnrpc_GetTransactionsRequest().serializedData(), MessageResponseCallback(emitter: emitter))
119-
120+
120121
return Disposables.create()
121122
}
122123
}
123124

124-
init(filesDir: String) {
125-
self.filesDir = filesDir
126-
}
127-
128-
private func genSeedSingle() -> Single<Lnrpc_GenSeedResponse> {
125+
var newSeedSingle: Single<Lnrpc_GenSeedResponse> {
129126
Single.create { emitter in
130127
LndmobileGenSeed(try! Lnrpc_GenSeedRequest().serializedData(), MessageResponseCallback(emitter: emitter))
131128

132129
return Disposables.create()
133130
}
134131
}
135132

133+
init(filesDir: String) throws {
134+
self.filesDir = filesDir
135+
136+
// start Lndmobile daemon
137+
let args = "--lnddir=\(filesDir) --bitcoin.active --bitcoin.mainnet --debuglevel=warn --no-macaroons --nolisten --norest --bitcoin.node=neutrino --routing.assumechanvalid --debuglevel=info"
138+
139+
_ = try Single<Void>.create { [weak self] emitter in
140+
LndmobileStart(args, VoidResponseCallback(emitter: emitter), RpcReadyCallback(self))
141+
142+
return Disposables.create()
143+
}.toBlocking().first()
144+
}
145+
136146
func scheduleStatusUpdates() {
137147
Observable<Int>.interval(.seconds(3), scheduler: SerialDispatchQueueScheduler(qos: .background))
138148
.flatMap { [weak self] _ -> Observable<NodeStatus> in
@@ -197,7 +207,7 @@ class LocalLnd: ILndNode {
197207
func closeChannelSingle(request: Lnrpc_CloseChannelRequest) throws -> Observable<Lnrpc_CloseStatusUpdate> {
198208
Observable.create { emitter in
199209
LndmobileCloseChannel(try! request.serializedData(), MessageResponseStream(emitter: emitter))
200-
210+
201211
return Disposables.create()
202212
}
203213
}
@@ -210,65 +220,9 @@ class LocalLnd: ILndNode {
210220
}
211221
}
212222

213-
func start() -> Single<Void> {
214-
let args = "--lnddir=\(filesDir) --bitcoin.active --bitcoin.mainnet --debuglevel=warn --no-macaroons --nolisten --norest --bitcoin.node=neutrino --routing.assumechanvalid --debuglevel=info"
215-
216-
return Single<Void>.create { emitter in
217-
LndmobileStart(args, VoidResponseCallback(emitter: emitter), VoidResponseCallback(emitter: nil))
218-
219-
return Disposables.create()
220-
}
221-
}
222-
223-
func startAndUnlock(password: String) {
224-
start()
225-
.flatMap { [weak self] _ in
226-
var request = Lnrpc_UnlockWalletRequest()
227-
request.walletPassword = Data(Array(password.utf8))
228-
229-
return self?.unlockWalletSingle(request: request) ?? Single.error(NodeNotRetained())
230-
}
231-
.subscribe(
232-
onSuccess: { [weak self] in self?.scheduleStatusUpdates() },
233-
onError: { [weak self] in self?.status = .error($0) }
234-
)
235-
.disposed(by: disposeBag)
236-
}
237-
238-
func createWalletSingle(password: String) -> Single<[String]> {
239-
genSeedSingle()
240-
.flatMap { [weak self] genSeedResponse in
241-
guard let node = self else {
242-
return Single<[String]>.error(NodeNotRetained())
243-
}
244-
245-
return node.initWalletSingle(mnemonicWords: genSeedResponse.cipherSeedMnemonic, password: password, recoveryWindow: 0)
246-
.do(
247-
onSuccess: { [weak self] _ in self?.scheduleStatusUpdates() },
248-
onError: { [weak self] in self?.status = .error($0) }
249-
)
250-
.map { _ in
251-
genSeedResponse.cipherSeedMnemonic
252-
}
253-
}
254-
}
255-
256-
func restoreWalletSingle(words: [String], password: String) -> Single<Void> {
257-
initWalletSingle(mnemonicWords: words, password: password)
258-
.do(
259-
onSuccess: { [weak self] _ in self?.scheduleStatusUpdates() },
260-
onError: { [weak self] in self?.status = .error($0) }
261-
)
262-
}
263-
264-
func initWalletSingle(mnemonicWords: [String], password: String, recoveryWindow: Int32 = 100) -> Single<Void> {
223+
func initWalletSingle(request: Lnrpc_InitWalletRequest) -> Single<Void> {
265224
Single.create { emitter in
266-
var msg = Lnrpc_InitWalletRequest()
267-
msg.cipherSeedMnemonic = mnemonicWords
268-
msg.walletPassword = Data(Array(password.utf8))
269-
msg.recoveryWindow = recoveryWindow
270-
271-
LndmobileInitWallet(try! msg.serializedData(), VoidResponseCallback(emitter: emitter))
225+
LndmobileInitWallet(try! request.serializedData(), VoidResponseCallback(emitter: emitter))
272226

273227
return Disposables.create()
274228
}
@@ -284,3 +238,13 @@ class LocalLnd: ILndNode {
284238
}
285239
}
286240
}
241+
242+
extension LocalLnd: RpcReadyCallbackDelegate {
243+
func RpcServerStartFailed(error: Error) {
244+
status = .error(error)
245+
}
246+
247+
func rpcReady() {
248+
scheduleStatusUpdates()
249+
}
250+
}

0 commit comments

Comments
 (0)