Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable switching of networks and server #158

Merged
merged 61 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from 49 commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
f5379a5
Add new LoadingView
danielnordh Jan 16, 2025
76d8269
Use AppState for start/onboarding
danielnordh Jan 16, 2025
0305807
Remove unused StartView and viewModel
danielnordh Jan 16, 2025
45d8582
Add ErrorView for showing startup errors
danielnordh Jan 16, 2025
3079d31
Merge branch 'reez:main' into main
danielnordh Jan 17, 2025
6428c49
Merge branch 'main' of https://github.com/danielnordh/Monday
danielnordh Jan 17, 2025
eb052d3
Merge branch 'main' of https://github.com/danielnordh/Monday
danielnordh Jan 20, 2025
a05d436
Move stored network to BackupInfo
danielnordh Jan 20, 2025
6d63c16
Move serverURL into BackupInfo
danielnordh Jan 20, 2025
8fa5246
Fix Picker issue where Server would not be set correctly
danielnordh Jan 20, 2025
6ba6da3
Refactor naming, user server instead of esplora for futureproofing
danielnordh Jan 20, 2025
e770ded
Remove unused parameter
danielnordh Jan 20, 2025
4e973c6
WIP, separate viewModel for NetworkSettings
danielnordh Jan 20, 2025
9fc82ef
Merge branch 'main' into networkswitch
danielnordh Jan 20, 2025
265c9f7
Swift format
danielnordh Jan 20, 2025
bf3710c
Refactor networksettingsviewmodel
danielnordh Jan 20, 2025
86493cd
Use NetworkSettingsView from Settings (but doesn't yet change)
danielnordh Jan 20, 2025
b7fb7a5
WIP restart, but UI doesn't respond
danielnordh Jan 23, 2025
c451ad0
Swift format
danielnordh Jan 23, 2025
a3c8afb
Update LDKNodeMonday/Utilities/Constants.swift
danielnordh Jan 23, 2025
0a39244
Fail when there is no available server
danielnordh Jan 23, 2025
338eea4
Fix error from github commit suggestion
danielnordh Jan 23, 2025
96e6638
WIP, guard for no saved network/server
danielnordh Jan 23, 2025
a6e173d
Create global function for availableServers
danielnordh Jan 23, 2025
9461068
Use general function for getting availableServers
danielnordh Jan 23, 2025
f7f0501
Swift format
danielnordh Jan 23, 2025
3453ded
Handle errors
danielnordh Jan 23, 2025
5547cec
Merge branch 'main' into networkswitch
danielnordh Jan 23, 2025
88e23e7
Implement WalletClient, network switching works
danielnordh Jan 27, 2025
912fe7e
Move delete() logic to walletClient
danielnordh Jan 27, 2025
4ec5ab7
Swift format
danielnordh Jan 27, 2025
598432e
Don't stop node if not running
danielnordh Jan 27, 2025
f32778d
Set network and server on node start
danielnordh Jan 27, 2025
03f842a
Add getServer()
danielnordh Jan 27, 2025
5021067
Use NetworkSettingsViewModel in onboarding, create wallet on WalletCl…
danielnordh Jan 27, 2025
f0fa753
Merge branch 'reez:main' into main
danielnordh Jan 27, 2025
d62476f
Don't save network if onboarding (no backupInfo yet)
danielnordh Jan 28, 2025
a582522
Use NetworkSettingsViewModel for selected network and server
danielnordh Jan 28, 2025
16677ba
Swift format
danielnordh Jan 28, 2025
86627bd
Remove TODO
danielnordh Jan 28, 2025
b64a5d7
Add reset() to LightningClient to handle delete properly
danielnordh Jan 28, 2025
726cd64
Don't save on networkSettingsViewModel switch
danielnordh Jan 28, 2025
b1e4e82
Un-refactor SettingsView
danielnordh Jan 28, 2025
54e44b1
Further un-refactoring of settingsview
danielnordh Jan 28, 2025
4eb1f51
Swift format
danielnordh Jan 28, 2025
30c1645
Coderabbit suggestion
danielnordh Jan 29, 2025
ca99376
Coderabbit suggestion
danielnordh Jan 29, 2025
ddd97dc
Simplify by not using NetworkSettingsViewModel
danielnordh Jan 29, 2025
8ffd850
Simplify alert logic
danielnordh Jan 29, 2025
cfb0631
Correct ldk-node version
danielnordh Jan 29, 2025
8a377d7
Use appError from WalletClient
danielnordh Jan 29, 2025
6888795
Merge branch 'networkswitch' of https://github.com/danielnordh/Monday…
danielnordh Jan 29, 2025
f56a805
LDK-node package
danielnordh Jan 29, 2025
7d80682
Swift format
danielnordh Jan 29, 2025
54b9d17
Remove unnecessary setting of tempNetwork when setting tempServer, ha…
danielnordh Jan 30, 2025
635a7dd
Bugfix: start with saved server
danielnordh Jan 30, 2025
0a64fe6
Refactor, coderabbit suggestion
danielnordh Jan 30, 2025
f4f2300
Swift format
danielnordh Jan 30, 2025
e177028
Apply Onboarding animations from #157
danielnordh Jan 30, 2025
855fed8
Remove unused parameter
danielnordh Jan 30, 2025
b86c98f
Refactor handleRestart, partial Coderabbit suggestion
danielnordh Jan 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion LDKNodeMonday.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
/* Begin PBXBuildFile section */
655574802D398A750064F859 /* LoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6555747F2D398A750064F859 /* LoadingView.swift */; };
655574822D3994E10064F859 /* ErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 655574812D3994E10064F859 /* ErrorView.swift */; };
655C19042D42AB1500AC5F72 /* WalletClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 655C19032D42AB1500AC5F72 /* WalletClient.swift */; };
65875A932CCB9809000D3E70 /* LDKNode in Frameworks */ = {isa = PBXBuildFile; productRef = 65875A922CCB9809000D3E70 /* LDKNode */; };
659EE6952CF8D4990064ED78 /* ImportWalletView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 659EE6942CF8D4990064ED78 /* ImportWalletView.swift */; };
65A406632D070CBD00EA331E /* NetworkSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65A406622D070CBD00EA331E /* NetworkSettingsView.swift */; };
Expand Down Expand Up @@ -95,6 +96,7 @@
/* Begin PBXFileReference section */
6555747F2D398A750064F859 /* LoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingView.swift; sourceTree = "<group>"; };
655574812D3994E10064F859 /* ErrorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorView.swift; sourceTree = "<group>"; };
655C19032D42AB1500AC5F72 /* WalletClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletClient.swift; sourceTree = "<group>"; };
659EE6942CF8D4990064ED78 /* ImportWalletView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportWalletView.swift; sourceTree = "<group>"; };
65A406622D070CBD00EA331E /* NetworkSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkSettingsView.swift; sourceTree = "<group>"; };
AE00550D2B479EF000100797 /* OnboardingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -478,6 +480,7 @@
isa = PBXGroup;
children = (
AE17E8D929A402E30058C9C9 /* LDKNodeMondayApp.swift */,
655C19032D42AB1500AC5F72 /* WalletClient.swift */,
);
path = App;
sourceTree = "<group>";
Expand Down Expand Up @@ -678,6 +681,7 @@
AE6BB56F2A008CBA009E16E3 /* UInt64+Extensions.swift in Sources */,
AE49E85A2A2536D4002623E8 /* ChannelAddViewModel.swift in Sources */,
AE0055142B4895B500100797 /* SeedViewModel.swift in Sources */,
655C19042D42AB1500AC5F72 /* WalletClient.swift in Sources */,
AE80C2022C4AB38D006E7193 /* BIP21ViewModel.swift in Sources */,
AE7D3FAB2A4263AE00EAE730 /* PaymentsView.swift in Sources */,
AE80116D29A59AF4009B9967 /* ChannelAddView.swift in Sources */,
Expand Down Expand Up @@ -909,7 +913,7 @@
repositoryURL = "https://github.com/lightningdevkit/ldk-node.git";
requirement = {
kind = exactVersion;
version = 0.4.3;
version = 0.4.2;
};
};
AE01C5AE2AB3BEED00F28C7E /* XCRemoteSwiftPackageReference "KeychainAccess" */ = {
Expand Down
56 changes: 12 additions & 44 deletions LDKNodeMonday/App/LDKNodeMondayApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,30 @@ struct LDKNodeMondayApp: App {

@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

private let lightningClient: LightningNodeClient = .live
@State private var appState = AppState.loading
@State private var walletClient = WalletClient(keyClient: .live)
@State private var appError: Error?
@State private var navigationPath = NavigationPath()

init() {
AppDelegate.shared.lightningClient = lightningClient
AppDelegate.shared.walletClient = walletClient
}

var body: some Scene {
WindowGroup {
NavigationStack(path: $navigationPath) {
switch appState {
switch walletClient.appState {
case .onboarding:
OnboardingView(
viewModel: .init(appState: $appState, lightningClient: lightningClient)
viewModel: .init(
walletClient: $walletClient
)
)
case .wallet:
BitcoinView(
viewModel: .init(
appState: $appState,
walletClient: $walletClient,
priceClient: .live,
lightningClient: lightningClient
lightningClient: walletClient.lightningClient
),
sendNavigationPath: $navigationPath
)
Expand All @@ -44,54 +45,21 @@ struct LDKNodeMondayApp: App {
LoadingView()
}
}
.onChange(of: appState) { oldValue, newValue in
.onChange(of: walletClient.appState) { oldValue, newValue in
navigationPath = NavigationPath()
}
.task {
await start()
}
}
}

func start() async {
var backupInfo: BackupInfo?

backupInfo = try? KeyClient.live.getBackupInfo()

if backupInfo != nil {
do {
// TODO: .start could take parameters from backupInfo (seed, network, url, lsp)
try await lightningClient.start()
lightningClient.listenForEvents()
await MainActor.run {
self.appState = .wallet
}
} catch let error {
await MainActor.run {
self.appError = error
self.appState = .error
}
}
} else {
await MainActor.run {
self.appState = .onboarding
await walletClient.start()
}
}
}
}

class AppDelegate: NSObject, UIApplicationDelegate {
static let shared = AppDelegate()
var lightningClient: LightningNodeClient?
var walletClient: WalletClient?

func applicationWillTerminate(_ application: UIApplication) {
try? lightningClient?.stop()
walletClient?.stop()
}
}

public enum AppState {
case onboarding
case wallet
case loading
case error
}
121 changes: 121 additions & 0 deletions LDKNodeMonday/App/WalletClient.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
//
// WalletClient.swift
// LDKNodeMonday
//
// Created by Daniel Nordh on 23/01/2025.
//

import Foundation
import LDKNode
import SwiftUI

@Observable
public class WalletClient {

public var keyClient: KeyClient
public var lightningClient: LightningNodeClient
public var network = Network.signet
public var server = EsploraServer.mutiny_signet
public var appState = AppState.loading
public var appError: Error?

public init(keyClient: KeyClient) {
self.keyClient = keyClient
self.lightningClient = .live
}

func createWallet(seedPhrase: String, network: Network, server: EsploraServer) async {
do {
let backupInfo = BackupInfo(
mnemonic: seedPhrase == "" ? generateEntropyMnemonic() : seedPhrase,
networkString: network.description,
serverURL: server.url
)
try keyClient.saveBackupInfo(backupInfo)
await self.start()
} catch let error {
await MainActor.run {
self.appError = error
self.appState = .error
}
}
}

func start() async {
var backupInfo: BackupInfo?
backupInfo = try? KeyClient.live.getBackupInfo()

if backupInfo != nil {
do {
try await lightningClient.start()
lightningClient.listenForEvents()
await MainActor.run {
self.network = lightningClient.getNetwork()
self.server = lightningClient.getServer()
self.appState = .wallet
}
} catch let error {
await MainActor.run {
self.appError = error
self.appState = .error
}
}
} else {
await MainActor.run {
self.appState = .onboarding
}
}
}

func stop() {
try? self.lightningClient.stop()
}
Comment on lines +70 to +72
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve error handling in stop() method.

The current implementation silently ignores errors, which could mask important issues.

Consider proper error handling:

-    func stop() {
-        try? self.lightningClient.stop()
+    func stop() throws {
+        try self.lightningClient.stop()
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func stop() {
try? self.lightningClient.stop()
}
func stop() throws {
try self.lightningClient.stop()
}


func restart(newNetwork: Network, newServer: EsploraServer) async {
do {
await MainActor.run {
self.appState = .loading
}
try await lightningClient.restart()
lightningClient.listenForEvents()
await MainActor.run {
self.network = newNetwork
self.server = newServer
self.appState = .wallet
}
} catch let error {
debugPrint(error)
await MainActor.run {
self.appError = error
self.appState = .error
}
}
}

func delete() async {
do {
if lightningClient.status().isRunning {
try lightningClient.stop()
}
try lightningClient.deleteDocuments()
try lightningClient.deleteWallet()
try lightningClient.reset()

await MainActor.run {
self.appState = .onboarding
}
} catch let error {
await MainActor.run {
self.appError = error
self.appState = .error
}
}
}
}

public enum AppState {
case onboarding
case wallet
case loading
case error
}
2 changes: 1 addition & 1 deletion LDKNodeMonday/Service/KeyService/KeyService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ extension KeyService {
}
}

struct KeyClient {
public struct KeyClient {
let saveBackupInfo: (BackupInfo) throws -> Void
let getBackupInfo: () throws -> BackupInfo
let deleteBackupInfo: () throws -> Void
Expand Down
46 changes: 43 additions & 3 deletions LDKNodeMonday/Service/Lightning Service/LightningNodeService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,23 @@ import SwiftUI
import os

class LightningNodeService {
static var shared: LightningNodeService = LightningNodeService()
private static let lock = NSLock()
private static var _shared: LightningNodeService?
static var shared: LightningNodeService {
get {
lock.lock()
defer { lock.unlock() }
if _shared == nil {
_shared = LightningNodeService()
}
return _shared!
}
set {
lock.lock()
_shared = newValue
lock.unlock()
}
}
private let ldkNode: Node
private let keyService: KeyClient
var networkColor = Color.black
Expand Down Expand Up @@ -128,6 +144,21 @@ class LightningNodeService {
try ldkNode.stop()
}

func restart() async throws {
if LightningNodeService.shared.status().isRunning {
try LightningNodeService.shared.stop()
}
LightningNodeService._shared = nil
try await LightningNodeService.shared.start()
}

func reset() throws {
if LightningNodeService.shared.status().isRunning {
try LightningNodeService.shared.stop()
}
LightningNodeService._shared = nil
}

func nodeId() -> String {
let nodeId = ldkNode.nodeId()
return nodeId
Expand Down Expand Up @@ -295,9 +326,11 @@ extension LightningNodeService {
}
}

struct LightningNodeClient {
public struct LightningNodeClient {
let start: () async throws -> Void
let stop: () throws -> Void
let restart: () async throws -> Void
let reset: () throws -> Void
let nodeId: () -> String
let newAddress: () async throws -> String
let spendableOnchainBalanceSats: () async -> UInt64
Expand All @@ -321,6 +354,7 @@ struct LightningNodeClient {
let getBackupInfo: () throws -> BackupInfo
let deleteDocuments: () throws -> Void
let getNetwork: () -> Network
let getServer: () -> EsploraServer
let getNetworkColor: () -> Color
let listenForEvents: () -> Void
}
Expand All @@ -329,6 +363,8 @@ extension LightningNodeClient {
static let live = Self(
start: { try await LightningNodeService.shared.start() },
stop: { try LightningNodeService.shared.stop() },
restart: { try await LightningNodeService.shared.restart() },
reset: { try LightningNodeService.shared.reset() },
nodeId: { LightningNodeService.shared.nodeId() },
newAddress: { try await LightningNodeService.shared.newAddress() },
spendableOnchainBalanceSats: {
Expand Down Expand Up @@ -390,8 +426,9 @@ extension LightningNodeClient {
getBackupInfo: { try LightningNodeService.shared.getBackupInfo() },
deleteDocuments: { try LightningNodeService.shared.deleteDocuments() },
getNetwork: { LightningNodeService.shared.network },
getServer: { LightningNodeService.shared.server },
getNetworkColor: { LightningNodeService.shared.networkColor },
listenForEvents: {}
listenForEvents: { LightningNodeService.shared.listenForEvents() }
)
}

Expand All @@ -400,6 +437,8 @@ extension LightningNodeClient {
static let mock = Self(
start: {},
stop: {},
restart: {},
reset: {},
nodeId: { "038474837483784378437843784378437843784378" },
newAddress: { "tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx" },
spendableOnchainBalanceSats: { 100_000 },
Expand Down Expand Up @@ -445,6 +484,7 @@ extension LightningNodeClient {
},
deleteDocuments: {},
getNetwork: { .signet },
getServer: { .mutiny_signet },
getNetworkColor: { .orange },
listenForEvents: {}
)
Expand Down
6 changes: 3 additions & 3 deletions LDKNodeMonday/View Model/Home/BitcoinViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import LDKNode
import SwiftUI

class BitcoinViewModel: ObservableObject {
@Binding var appState: AppState
@Binding var walletClient: WalletClient
@Published var bitcoinViewError: MondayError?
@Published var networkColor = Color.gray
@Published var status: NodeStatus?
Expand Down Expand Up @@ -39,11 +39,11 @@ class BitcoinViewModel: ObservableObject {
}

init(
appState: Binding<AppState>,
walletClient: Binding<WalletClient>,
priceClient: PriceClient,
lightningClient: LightningNodeClient
) {
_appState = appState
_walletClient = walletClient
self.priceClient = priceClient
self.lightningClient = lightningClient
}
Expand Down
Loading