Skip to content

Commit c6f12c9

Browse files
authored
refactor: walletclient
1 parent c255bcb commit c6f12c9

7 files changed

Lines changed: 130 additions & 99 deletions

File tree

LDKNodeMonday/App/LDKNodeMondayApp.swift

Lines changed: 52 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,43 +12,67 @@ struct LDKNodeMondayApp: App {
1212

1313
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
1414

15-
@State private var walletClient = WalletClient(appMode: .live)
15+
@State private var walletClient: WalletClient? = nil
1616
@State private var navigationPath = NavigationPath()
1717

18-
init() {
19-
AppDelegate.shared.walletClient = walletClient
20-
}
18+
init() {}
2119

2220
var body: some Scene {
2321
WindowGroup {
24-
NavigationStack(path: $navigationPath) {
25-
switch walletClient.appState {
26-
case .onboarding:
27-
OnboardingView(
28-
viewModel: .init(
29-
walletClient: $walletClient
30-
)
31-
)
32-
case .wallet:
33-
BitcoinView(
34-
viewModel: .init(
35-
walletClient: $walletClient,
36-
priceClient: .live,
37-
lightningClient: walletClient.lightningClient
38-
),
39-
sendNavigationPath: $navigationPath
40-
)
41-
case .error:
42-
ErrorView(error: walletClient.appError)
43-
default:
22+
Group {
23+
if let walletClient = walletClient {
24+
NavigationStack(path: $navigationPath) {
25+
switch walletClient.appState {
26+
case .onboarding:
27+
OnboardingView(
28+
viewModel: .init(
29+
walletClient: Binding(
30+
get: { self.walletClient! },
31+
set: { self.walletClient = $0 }
32+
)
33+
)
34+
)
35+
case .wallet:
36+
BitcoinView(
37+
viewModel: .init(
38+
walletClient: Binding(
39+
get: { self.walletClient! },
40+
set: { self.walletClient = $0 }
41+
),
42+
priceClient: .live,
43+
lightningClient: walletClient.lightningClient
44+
),
45+
sendNavigationPath: $navigationPath
46+
)
47+
case .error:
48+
ErrorView(error: walletClient.appError)
49+
default:
50+
LoadingView()
51+
}
52+
}
53+
.onChange(of: walletClient.appState) { oldValue, newValue in
54+
navigationPath = NavigationPath()
55+
}
56+
.task {
57+
await walletClient.start()
58+
}
59+
} else {
4460
LoadingView()
4561
}
4662
}
47-
.onChange(of: walletClient.appState) { oldValue, newValue in
48-
navigationPath = NavigationPath()
49-
}
5063
.task {
51-
await walletClient.start()
64+
if walletClient == nil {
65+
do {
66+
let client = try await WalletClient.create(appMode: .live)
67+
walletClient = client
68+
AppDelegate.shared.walletClient = client
69+
} catch {
70+
let errorClient = WalletClient.mock
71+
errorClient.appState = .error
72+
errorClient.appError = error
73+
walletClient = errorClient
74+
}
75+
}
5276
}
5377
}
5478
}

LDKNodeMonday/App/WalletClient.swift

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,24 @@ public class WalletClient {
2020
public var appState = AppState.loading
2121
public var appError: Error?
2222

23-
public init(appMode: AppMode) {
23+
private init(appMode: AppMode, keyClient: KeyClient, lightningClient: LightningNodeClient) {
2424
self.appMode = appMode
25+
self.keyClient = keyClient
26+
self.lightningClient = lightningClient
27+
}
28+
29+
public static func create(appMode: AppMode) async throws -> WalletClient {
2530
switch appMode {
2631
case .live:
27-
self.keyClient = .live
28-
self.lightningClient = .live
32+
try await LightningNodeService.initializeShared()
33+
return WalletClient(appMode: .live, keyClient: .live, lightningClient: .live)
2934
case .mock:
30-
self.keyClient = .mock
31-
self.lightningClient = .mock
35+
return WalletClient(appMode: .mock, keyClient: .mock, lightningClient: .mock)
3236
}
3337
}
3438

39+
public static let mock = WalletClient(appMode: .mock, keyClient: .mock, lightningClient: .mock)
40+
3541
func createWallet(seedPhrase: String, network: Network, server: EsploraServer) async {
3642
do {
3743
let backupInfo = BackupInfo(

LDKNodeMonday/Service/Lightning Service/LightningNodeService.swift

Lines changed: 62 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ class LightningNodeService {
1818
lock.lock()
1919
defer { lock.unlock() }
2020
if _shared == nil {
21-
_shared = LightningNodeService()
21+
fatalError(
22+
"LightningNodeService.shared must be set using initializeShared() before use."
23+
)
2224
}
2325
return _shared!
2426
}
@@ -34,88 +36,75 @@ class LightningNodeService {
3436
var network: Network
3537
var server: EsploraServer
3638

37-
init(
38-
keyService: KeyClient = .live
39-
) {
39+
private init(ldkNode: Node, keyService: KeyClient, network: Network, server: EsploraServer) {
40+
self.ldkNode = ldkNode
41+
self.keyService = keyService
42+
self.network = network
43+
self.server = server
44+
}
4045

41-
if let backupInfo = try? KeyClient.live.getBackupInfo() {
42-
guard let network = Network(stringValue: backupInfo.networkString) else {
43-
// This should never happen, but if it does:
44-
fatalError("Configuration error: No Network found in BackupInfo")
46+
static func create(keyService: KeyClient = .live) async throws -> LightningNodeService {
47+
let backupInfo = try? KeyClient.live.getBackupInfo()
48+
let network: Network
49+
let server: EsploraServer
50+
if let backupInfo {
51+
guard let n = Network(stringValue: backupInfo.networkString) else {
52+
throw NSError(
53+
domain: "LightningNodeService",
54+
code: 1,
55+
userInfo: [NSLocalizedDescriptionKey: "No Network found in BackupInfo"]
56+
)
4557
}
46-
self.network = network
47-
58+
network = n
4859
guard
49-
let server =
50-
EsploraServer(URLString: backupInfo.serverURL)
51-
?? availableServers(network: network).first
60+
let s = EsploraServer(URLString: backupInfo.serverURL)
61+
?? availableServers(network: n).first
5262
else {
53-
// This should never happen, but if it does:
54-
fatalError("Configuration error: No Esplora servers available for \(network)")
63+
throw NSError(
64+
domain: "LightningNodeService",
65+
code: 2,
66+
userInfo: [
67+
NSLocalizedDescriptionKey: "No Esplora servers available for \(network)"
68+
]
69+
)
5570
}
56-
self.server = server
71+
server = s
5772
} else {
58-
self.network = .signet
59-
self.server = .mutiny_signet
73+
network = .signet
74+
server = .mutiny_signet
6075
}
6176

62-
self.keyService = keyService
63-
6477
let documentsPath = FileManager.default.getDocumentsDirectoryPath()
6578
let networkPath = URL(fileURLWithPath: documentsPath)
6679
.appendingPathComponent(network.description)
6780
.path
6881
let logPath = networkPath + "/logs"
69-
70-
try? FileManager.default.createDirectory(
71-
atPath: logPath,
72-
withIntermediateDirectories: true
73-
)
74-
75-
// This is what `Config` looks like now, need to find out where `logDirPath` and `logLevel` are now
76-
77-
// public struct Config {
78-
// public var storageDirPath: String
79-
// public var network: Network
80-
// public var listeningAddresses: [SocketAddress]?
81-
// public var nodeAlias: NodeAlias?
82-
// public var trustedPeers0conf: [PublicKey]
83-
// public var probingLiquidityLimitMultiplier: UInt64
84-
// public var anchorChannelsConfig: AnchorChannelsConfig?
85-
// public var sendingParameters: SendingParameters?
82+
try? FileManager.default.createDirectory(atPath: logPath, withIntermediateDirectories: true)
8683

8784
var config = defaultConfig()
8885
config.storageDirPath = networkPath
89-
// config.logDirPath = logPath
90-
config.network = self.network
91-
config.trustedPeers0conf = [
92-
Constants.Config.LiquiditySourceLsps2.Signet.megalith.nodeId
93-
]
94-
// config.logLevel = .trace
95-
86+
config.network = network
87+
config.trustedPeers0conf = [Constants.Config.LiquiditySourceLsps2.Signet.megalith.nodeId]
9688
let anchor_cfg = AnchorChannelsConfig(
97-
trustedPeersNoReserve: [
98-
Constants.Config.LiquiditySourceLsps2.Signet.megalith.nodeId
99-
],
89+
trustedPeersNoReserve: [Constants.Config.LiquiditySourceLsps2.Signet.megalith.nodeId],
10090
perChannelReserveSats: UInt64(0)
10191
)
10292
config.anchorChannelsConfig = .some(anchor_cfg)
103-
10493

10594
let nodeBuilder = Builder.fromConfig(config: config)
106-
nodeBuilder.setChainSourceEsplora(serverUrl: self.server.url, config: nil)
107-
108-
switch self.network {
95+
nodeBuilder.setChainSourceEsplora(serverUrl: server.url, config: nil)
96+
var networkColor = Color.black
97+
switch network {
10998
case .bitcoin:
11099
nodeBuilder.setGossipSourceRgs(
111100
rgsServerUrl: Constants.Config.RGSServerURLNetwork.bitcoin
112101
)
113-
self.networkColor = Constants.BitcoinNetworkColor.bitcoin.color
102+
networkColor = Constants.BitcoinNetworkColor.bitcoin.color
114103
case .testnet:
115104
nodeBuilder.setGossipSourceRgs(
116105
rgsServerUrl: Constants.Config.RGSServerURLNetwork.testnet
117106
)
118-
self.networkColor = Constants.BitcoinNetworkColor.testnet.color
107+
networkColor = Constants.BitcoinNetworkColor.testnet.color
119108
case .signet:
120109
nodeBuilder.setGossipSourceRgs(
121110
rgsServerUrl: Constants.Config.RGSServerURLNetwork.signet
@@ -125,9 +114,9 @@ class LightningNodeService {
125114
address: Constants.Config.LiquiditySourceLsps2.Signet.megalith.address,
126115
token: Constants.Config.LiquiditySourceLsps2.Signet.megalith.token
127116
)
128-
self.networkColor = Constants.BitcoinNetworkColor.signet.color
117+
networkColor = Constants.BitcoinNetworkColor.signet.color
129118
case .regtest:
130-
self.networkColor = Constants.BitcoinNetworkColor.regtest.color
119+
networkColor = Constants.BitcoinNetworkColor.regtest.color
131120
}
132121

133122
let mnemonic: String
@@ -137,8 +126,8 @@ class LightningNodeService {
137126
let newMnemonic = generateEntropyMnemonic()
138127
let backupInfo = BackupInfo(
139128
mnemonic: newMnemonic,
140-
networkString: self.network.description,
141-
serverURL: self.server.url
129+
networkString: network.description,
130+
serverURL: server.url
142131
)
143132
try? keyService.saveBackupInfo(backupInfo)
144133
mnemonic = newMnemonic
@@ -149,16 +138,27 @@ class LightningNodeService {
149138
let newMnemonic = generateEntropyMnemonic()
150139
let backupInfo = BackupInfo(
151140
mnemonic: newMnemonic,
152-
networkString: self.network.description,
153-
serverURL: self.server.url
141+
networkString: network.description,
142+
serverURL: server.url
154143
)
155144
try? keyService.saveBackupInfo(backupInfo)
156145
mnemonic = newMnemonic
157146
}
158147
nodeBuilder.setEntropyBip39Mnemonic(mnemonic: mnemonic, passphrase: nil)
148+
let ldkNode = try await nodeBuilder.build()
149+
let service = LightningNodeService(
150+
ldkNode: ldkNode,
151+
keyService: keyService,
152+
network: network,
153+
server: server
154+
)
155+
service.networkColor = networkColor
156+
return service
157+
}
159158

160-
let ldkNode = try! nodeBuilder.build() // Handle error instead of "!"
161-
self.ldkNode = ldkNode
159+
static func initializeShared(keyService: KeyClient = .live) async throws {
160+
let service = try await create(keyService: keyService)
161+
LightningNodeService.shared = service
162162
}
163163

164164
func start() async throws {
@@ -415,6 +415,7 @@ public struct LightningNodeClient {
415415
}
416416

417417
extension LightningNodeClient {
418+
/// NOTE: LightningNodeService.shared must be set via initializeShared() before using .live
418419
static let live = Self(
419420
start: { try await LightningNodeService.shared.start() },
420421
stop: { try LightningNodeService.shared.stop() },

LDKNodeMonday/View/Home/BitcoinView.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,11 +340,11 @@ extension DisplayBalanceType {
340340
#Preview {
341341
BitcoinView(
342342
viewModel: .init(
343-
walletClient: .constant(WalletClient(appMode: AppMode.mock)),
343+
walletClient: .constant(WalletClient.mock),
344344
priceClient: .mock,
345345
lightningClient: .mock
346346
),
347-
sendNavigationPath: .constant(.init())
347+
sendNavigationPath: .constant(NavigationPath())
348348
)
349349
}
350350
#endif

LDKNodeMonday/View/Home/NetworkSettingsView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,6 @@ struct NetworkSettingsView: View {
169169

170170
#if DEBUG
171171
#Preview {
172-
NetworkSettingsView(walletClient: .constant(WalletClient(appMode: AppMode.mock)))
172+
NetworkSettingsView(walletClient: .constant(WalletClient.mock))
173173
}
174174
#endif

LDKNodeMonday/View/Home/OnboardingView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ struct OnboardingView: View {
138138
#Preview {
139139
OnboardingView(
140140
viewModel: .init(
141-
walletClient: .constant(WalletClient(appMode: AppMode.mock))
141+
walletClient: .constant(WalletClient.mock)
142142
)
143143
)
144144
}

LDKNodeMonday/View/Settings/SettingsView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ struct SettingsView: View {
203203
#Preview {
204204
SettingsView(
205205
viewModel: .init(
206-
walletClient: .constant(WalletClient(appMode: AppMode.mock)),
206+
walletClient: .constant(WalletClient.mock),
207207
lightningClient: .mock
208208
)
209209

0 commit comments

Comments
 (0)