Skip to content
2 changes: 1 addition & 1 deletion Bitkit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -928,7 +928,7 @@
repositoryURL = "https://github.com/synonymdev/ldk-node";
requirement = {
kind = revision;
revision = c5698d00066e0e50f33696afc562d71023da2373;
revision = ae38eadab70fceb5dbe242bc02bf895581cb7c3f;
};
};
96DEA0382DE8BBA1009932BF /* XCRemoteSwiftPackageReference "bitkit-core" */ = {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

54 changes: 41 additions & 13 deletions Bitkit/Services/LightningService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@
onchainWalletSyncIntervalSecs: Env.walletSyncIntervalSecs,
lightningWalletSyncIntervalSecs: Env.walletSyncIntervalSecs,
feeRateCacheUpdateIntervalSecs: Env.walletSyncIntervalSecs
)
),
connectionTimeoutSecs: 10
)
builder.setChainSourceElectrum(serverUrl: resolvedElectrumServerUrl, config: electrumConfig)

Expand Down Expand Up @@ -124,19 +125,46 @@
builder.setEntropyBip39Mnemonic(mnemonic: mnemonic, passphrase: passphrase)

try await ServiceQueue.background(.ldk) {
if !lnurlAuthServerUrl.isEmpty {
self.node = try builder.buildWithVssStore(
vssUrl: vssUrl,
storeId: storeId,
lnurlAuthServerUrl: lnurlAuthServerUrl,
fixedHeaders: [:]
)
} else {
self.node = try builder.buildWithVssStoreAndFixedHeaders(
vssUrl: vssUrl,
storeId: storeId,
fixedHeaders: [:]
do {
if !lnurlAuthServerUrl.isEmpty {
self.node = try builder.buildWithVssStore(
vssUrl: vssUrl,
storeId: storeId,
lnurlAuthServerUrl: lnurlAuthServerUrl,
fixedHeaders: [:]
)
} else {
self.node = try builder.buildWithVssStoreAndFixedHeaders(
vssUrl: vssUrl,
storeId: storeId,
fixedHeaders: [:]
)
}
} catch let error as BuildError {
guard case .DangerousValue = error else { throw error }

// Stale ChannelMonitor vs ChannelManager — retry with accept_stale to recover.
Logger.warn(
"Build failed with DangerousValue. Retrying with accept_stale_channel_monitors for recovery.",
context: "Recovery"
)
builder.setAcceptStaleChannelMonitors(accept: true)

if !lnurlAuthServerUrl.isEmpty {
self.node = try builder.buildWithVssStore(
vssUrl: vssUrl,
storeId: storeId,
lnurlAuthServerUrl: lnurlAuthServerUrl,
fixedHeaders: [:]
)
} else {
self.node = try builder.buildWithVssStoreAndFixedHeaders(
vssUrl: vssUrl,
storeId: storeId,
fixedHeaders: [:]
)
}
Logger.info("Stale monitor recovery: build succeeded with accept_stale", context: "Recovery")
}
}

Expand Down Expand Up @@ -595,7 +623,7 @@
}

func closeChannel(_ channel: ChannelDetails, force: Bool = false, forceCloseReason: String? = nil) async throws {
guard let node else {

Check warning on line 626 in Bitkit/Services/LightningService.swift

View workflow job for this annotation

GitHub Actions / Run Tests

value 'node' was defined but never used; consider replacing with boolean test
throw AppError(serviceError: .nodeNotStarted)
}

Expand Down Expand Up @@ -1068,7 +1096,7 @@
onEvent?(event)

switch event {
case let .paymentSuccessful(paymentId, paymentHash, paymentPreimage, feePaidMsat):

Check warning on line 1099 in Bitkit/Services/LightningService.swift

View workflow job for this annotation

GitHub Actions / Run Tests

immutable value 'paymentPreimage' was never used; consider replacing with '_' or removing it
Logger.info("✅ Payment successful: paymentId: \(paymentId ?? "?") paymentHash: \(paymentHash) feePaidMsat: \(feePaidMsat ?? 0)")
Task {
let hash = paymentId ?? paymentHash
Expand All @@ -1093,7 +1121,7 @@
Logger.warn("No paymentId or paymentHash available for failed payment", context: "LightningService")
}
}
case let .paymentReceived(paymentId, paymentHash, amountMsat, feePaidMsat):

Check warning on line 1124 in Bitkit/Services/LightningService.swift

View workflow job for this annotation

GitHub Actions / Run Tests

immutable value 'feePaidMsat' was never used; consider replacing with '_' or removing it
Logger.info("🤑 Payment received: paymentId: \(paymentId ?? "?") paymentHash: \(paymentHash) amountMsat: \(amountMsat)")
Task {
let hash = paymentId ?? paymentHash
Expand All @@ -1103,7 +1131,7 @@
Logger.error("Failed to handle payment received for \(hash): \(error)", context: "LightningService")
}
}
case let .paymentClaimable(paymentId, paymentHash, claimableAmountMsat, claimDeadline, customRecords):

Check warning on line 1134 in Bitkit/Services/LightningService.swift

View workflow job for this annotation

GitHub Actions / Run Tests

immutable value 'customRecords' was never used; consider replacing with '_' or removing it

Check warning on line 1134 in Bitkit/Services/LightningService.swift

View workflow job for this annotation

GitHub Actions / Run Tests

immutable value 'claimDeadline' was never used; consider replacing with '_' or removing it
Logger.info(
"🫰 Payment claimable: paymentId: \(paymentId) paymentHash: \(paymentHash) claimableAmountMsat: \(claimableAmountMsat)"
)
Expand Down Expand Up @@ -1132,7 +1160,7 @@

if let channel {
await registerClosedChannel(channel: channel, reason: reasonString)
await MainActor.run {

Check warning on line 1163 in Bitkit/Services/LightningService.swift

View workflow job for this annotation

GitHub Actions / Run Tests

result of call to 'run(resultType:body:)' is unused
channelCache.removeValue(forKey: channelIdString)
}
} else {
Expand All @@ -1155,7 +1183,7 @@
Logger.error("Failed to handle transaction received for \(txid): \(error)", context: "LightningService")
}
}
case let .onchainTransactionConfirmed(txid, blockHash, blockHeight, confirmationTime, details):

Check warning on line 1186 in Bitkit/Services/LightningService.swift

View workflow job for this annotation

GitHub Actions / Run Tests

immutable value 'confirmationTime' was never used; consider replacing with '_' or removing it

Check warning on line 1186 in Bitkit/Services/LightningService.swift

View workflow job for this annotation

GitHub Actions / Run Tests

immutable value 'blockHash' was never used; consider replacing with '_' or removing it
Logger.info("✅ Onchain transaction confirmed: txid=\(txid) blockHeight=\(blockHeight) amountSats=\(details.amountSats)")
Task {
do {
Expand Down Expand Up @@ -1209,7 +1237,7 @@

// MARK: Balance Events

case let .balanceChanged(oldSpendableOnchain, newSpendableOnchain, oldTotalOnchain, newTotalOnchain, oldLightning, newLightning):

Check warning on line 1240 in Bitkit/Services/LightningService.swift

View workflow job for this annotation

GitHub Actions / Run Tests

immutable value 'newTotalOnchain' was never used; consider replacing with '_' or removing it

Check warning on line 1240 in Bitkit/Services/LightningService.swift

View workflow job for this annotation

GitHub Actions / Run Tests

immutable value 'oldTotalOnchain' was never used; consider replacing with '_' or removing it
Logger
.info("💰 Balance changed: onchain=\(oldSpendableOnchain)->\(newSpendableOnchain) lightning=\(oldLightning)->\(newLightning)")

Expand Down
3 changes: 3 additions & 0 deletions Bitkit/Utilities/Errors.swift
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,9 @@ struct AppError: LocalizedError {
case let .ReadFailed(message: ldkMessage):
message = "Read failed"
debugMessage = ldkMessage
case let .DangerousValue(message: ldkMessage):
message = "Dangerous value"
debugMessage = ldkMessage
case let .WriteFailed(message: ldkMessage):
message = "Write failed"
debugMessage = ldkMessage
Expand Down
28 changes: 14 additions & 14 deletions Bitkit/ViewModels/WalletViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -138,20 +138,20 @@ class WalletViewModel: ObservableObject {
}

// If no local migration data, try fetching from RN remote backup (one-time)
// if channelMigration == nil {
// let (remoteMigration, allRetrieved) = await fetchOrphanedChannelMonitorsIfNeeded(walletIndex: walletIndex)
// if let remoteMigration {
// channelMigration = ChannelDataMigration(
// // don't overwrite channel manager, we only need the monitors for the sweep
// channelManager: nil,
// channelMonitors: remoteMigration.channelMonitors.map { [UInt8]($0) }
// )
// MigrationsService.shared.pendingChannelMigration = nil
// }
// if allRetrieved {
// MigrationsService.shared.isChannelRecoveryChecked = true
// }
// }
if channelMigration == nil {
let (remoteMigration, allRetrieved) = await fetchOrphanedChannelMonitorsIfNeeded(walletIndex: walletIndex)
if let remoteMigration {
channelMigration = ChannelDataMigration(
// don't overwrite channel manager, we only need the monitors for the sweep
channelManager: nil,
channelMonitors: remoteMigration.channelMonitors.map { [UInt8]($0) }
)
MigrationsService.shared.pendingChannelMigration = nil
}
if allRetrieved {
MigrationsService.shared.isChannelRecoveryChecked = true
}
}

await runLegacyNetworkGraphCleanupIfNeeded()

Expand Down
Loading