Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
162 commits
Select commit Hold shift + click to select a range
03a771b
feat: spark emergency exit
ovitrif Nov 5, 2026
46ae755
fix: rebuild a spark exit whose fee chain lost a race
ovitrif Nov 5, 2026
5d18a23
fix: one notification for a lost spark exit
ovitrif Nov 5, 2026
57118a6
fix: keep lost spark exit leaves out of later exits
ovitrif Nov 5, 2026
0751b03
chore: merge feat/breez-spark-lightning
ovitrif Nov 5, 2026
7220fd0
feat: spark exit uses bitkit electrs on mainnet
ovitrif Nov 5, 2026
1574688
fix: spark exit lost leaves from before the update
ovitrif Nov 5, 2026
d6d7463
fix: spark exit rebuilds when it stops moving
ovitrif Nov 5, 2026
7c8cf47
fix: spark exit keeps its pre-exit backup
ovitrif Nov 5, 2026
50b186a
fix: exit notifications open the exit
ovitrif Nov 5, 2026
df489cc
fix: spark exit shows a low fee rate when the mempool refuses it
ovitrif Nov 5, 2026
14bcdc2
chore: merge feat/breez-spark-lightning
ovitrif Nov 5, 2026
1a5d3dd
fix: spark exit waits for leaves the operators cannot locate yet
ovitrif Nov 5, 2026
8eac1b9
feat: spark exit funds each step separately and can pay a higher fee
ovitrif Nov 5, 2026
7c9dedb
fix: spark exit result leads with what reached savings
ovitrif Nov 5, 2026
495fca5
fix: spark exit stays quiet while a higher fee's payment confirms
ovitrif Nov 5, 2026
3d871fb
fix: spark exit sweeps fee change when network fees drop
ovitrif Nov 5, 2026
f8aad60
fix: spark exit rerun findings
ovitrif Nov 5, 2026
1cfce7a
fix: spark exit sends lone transactions as a package when the host re…
ovitrif Nov 5, 2026
3721f4b
fix: spark exit retries a refused fee change sweep
ovitrif Nov 6, 2026
328b29a
fix: spark exit retries a fee change sweep dropped from the mempool
ovitrif Nov 6, 2026
203d1df
chore: merge feat/breez-spark-lightning
ovitrif Nov 6, 2026
61a7d7a
fix: import libsecp256k1 in the spark exit sweep test
ovitrif Nov 6, 2026
649a7d0
chore: merge feat/breez-spark-lightning
ovitrif Nov 6, 2026
6563f7d
chore: merge feat/breez-spark-lightning
ovitrif Nov 6, 2026
ce7c767
chore: merge feat/breez-spark-lightning
ovitrif Nov 6, 2026
4b2feb5
fix: spark exit independent review findings
ovitrif Nov 6, 2026
28170b9
fix: spark exit bot review findings
ovitrif Nov 6, 2026
3331a5a
fix: spark exit background sweeps use the economy rate
ovitrif Nov 6, 2026
f7e5053
chore: merge feat/breez-spark-lightning
ovitrif Nov 6, 2026
d4df811
fix: spark exit keeps an unresolved funding payment
ovitrif Nov 7, 2026
6f0cdee
fix: spark exit findings from the android review
ovitrif Nov 7, 2026
46baea6
fix: spark exit home balances and start racing cancel
ovitrif Nov 7, 2026
e1b3052
fix: spark exit ended payments, top-up coins and sweep activity
ovitrif Nov 7, 2026
a4cd317
Merge remote-tracking branch 'origin/feat/breez-spark-lightning' into…
ovitrif Nov 9, 2026
1ac1096
Merge remote-tracking branch 'origin/feat/breez-spark-lightning' into…
ovitrif Nov 9, 2026
a56c28f
fix: forget the spark exit quote on wallet wipe
ovitrif Nov 9, 2026
d308217
fix: quote the spark exit again when its leaves changed before the start
ovitrif Nov 9, 2026
20736be
fix: cap the spark exit's leftover sweep fee after a refusal
ovitrif Nov 9, 2026
e7401ce
fix: show the savings payment fee and total on spark exit confirm
ovitrif Nov 9, 2026
2b0da4a
fix: refuse paying a spark invoice again over a channel during an exit
ovitrif Nov 9, 2026
6934e05
fix: use the brand orange accent on spark exit screens
ovitrif Nov 9, 2026
6d6d8a5
fix: match spark exit note colours to android
ovitrif Nov 9, 2026
7363979
fix: follow a spark exit fee bump paid after the exit ended
ovitrif Nov 9, 2026
a456b6a
fix: keep the spark exit transfer while failed leaves are retried
ovitrif Nov 9, 2026
f0ee36d
fix: keep a spark exit sweep pending until its leftover is read
ovitrif Nov 9, 2026
77a1e49
fix: keep the spark exit transfer while failed leaves await retry
ovitrif Nov 9, 2026
736e552
fix: remind about the rest of a short spark exit savings payment
ovitrif Nov 9, 2026
ce4f86b
fix: retry spark exit leaves a partial build skipped
ovitrif Nov 9, 2026
f54a246
fix: show the spark exit sweep version that confirmed
ovitrif Nov 9, 2026
6ad6a85
fix: keep the spark exit start going when its requote write fails
ovitrif Nov 9, 2026
1cf0841
fix: translate the spark exit strings
ovitrif Nov 9, 2026
118b5e1
fix: show the spark exit savings fee error without fee rates
ovitrif Nov 9, 2026
f4ca8e6
fix: hold spark exit ticks until its start settles
ovitrif Nov 9, 2026
f212534
fix: take lost spark exit leaves out of the transfer
ovitrif Nov 9, 2026
2a9dce8
Merge remote-tracking branch 'origin/feat/breez-spark-lightning' into…
ovitrif Nov 9, 2026
5dfc2ca
fix: ask for fee funding a skipped spark exit leaf's retry needs
ovitrif Nov 9, 2026
dfc1716
Merge remote-tracking branch 'origin/feat/breez-spark-lightning' into…
ovitrif Nov 9, 2026
66cbf30
fix: end an unfunded spark exit leaf retry after its week
ovitrif Nov 9, 2026
fa8372a
fix: keep spark exit leaves skipped beside failed cooperative ones
ovitrif Nov 9, 2026
9b06220
fix: count spark exit leaves let go after a week as left on spark
ovitrif Nov 9, 2026
fa5c153
Merge remote-tracking branch 'origin/feat/breez-spark-lightning' into…
ovitrif Nov 9, 2026
b4f6555
fix: show no cancelled spark exit's funding for the next exit
ovitrif Nov 9, 2026
6c55fff
Merge remote-tracking branch 'origin/feat/breez-spark-lightning' into…
ovitrif Nov 9, 2026
611c9be
feat: offer to pay a refused spark exit savings payment again
ovitrif Nov 9, 2026
b62ed54
fix: let go of an unpaid spark exit leaf ask without the sdk
ovitrif Nov 9, 2026
23627f4
fix: allow a higher spark exit fee once a failed-leaf retry built
ovitrif Nov 9, 2026
9803432
fix: keep a spark exit cancel out of its savings payment again
ovitrif Nov 9, 2026
2b4e07e
fix: translate the refused spark exit savings payment line
ovitrif Nov 9, 2026
b300672
fix: let no spark connect bring a wiped wallet back
ovitrif Nov 9, 2026
4488604
fix: offer no spark exit fee rate a leaf can't pay its exit at
ovitrif Nov 9, 2026
733d9a5
fix: keep spark exit reminders while a retry's steps confirm
ovitrif Nov 9, 2026
3ef3b37
Merge remote-tracking branch 'origin/feat/breez-spark-lightning' into…
ovitrif Nov 9, 2026
906cd79
Merge remote-tracking branch 'origin/feat/breez-spark-lightning' into…
ovitrif Nov 9, 2026
58c07a4
Merge remote-tracking branch 'origin/feat/breez-spark-lightning' into…
ovitrif Nov 10, 2026
4d1e36a
Merge remote-tracking branch 'origin/feat/breez-spark-lightning' into…
ovitrif Nov 10, 2026
64e62fc
Merge remote-tracking branch 'origin/feat/breez-spark-lightning' into…
ovitrif Nov 10, 2026
0abf0ab
fix: keep an interrupted exit start in its transfer
ovitrif Nov 10, 2026
86432fa
fix: import a salvaged exit's kept data before its rebuild
ovitrif Nov 10, 2026
4b9d3d0
fix: use the flat hourglass on exit steps
ovitrif Nov 10, 2026
1af9389
fix: align exit screens with the explore cell and accents
ovitrif Nov 10, 2026
8fcf7c5
fix: take the exit hourglass from the android vector
ovitrif Nov 10, 2026
7b73b66
fix: match the exit screens across apps
ovitrif Nov 10, 2026
5ebff50
fix: match exit spacing and dialogs across apps
ovitrif Nov 10, 2026
e8b1b94
Merge remote-tracking branch 'origin/feat/breez-spark-lightning' into…
ovitrif Nov 10, 2026
4b4b975
fix: keep the kept spark balance out of an exit
ovitrif Nov 10, 2026
6818189
fix: show spark as zero in spending during an exit
ovitrif Nov 10, 2026
172e564
fix: ask again for saved exit confirmations after a reorg
ovitrif Nov 10, 2026
1374063
fix: cap exit funding sends at the confirmed mining fee
ovitrif Nov 10, 2026
c1a7ee4
fix: keep the kept spark balance after a cancelled exit
ovitrif Nov 10, 2026
bb23267
chore: merge feat/breez-spark-lightning into feat/spark-emergency-exit
ovitrif Nov 10, 2026
48b2252
fix: approve the refused savings fee on the next fee bump confirm
ovitrif Nov 10, 2026
7968138
fix: keep the exit notification note above its buttons
ovitrif Nov 10, 2026
3311ff9
revert: keep the exit notification note above its buttons
ovitrif Nov 10, 2026
27b2ce1
fix: keep the exit notification note above its buttons
ovitrif Nov 10, 2026
536144c
fix: approve the refused savings fee on the next exit start
ovitrif Nov 10, 2026
80394fc
fix: keep the kept spark balance from the exit start
ovitrif Nov 10, 2026
56b7ea0
fix: forget the kept spark balance on a wipe
ovitrif Nov 10, 2026
5e9ddd7
chore: merge feat/breez-spark-lightning into feat/spark-emergency-exit
ovitrif Nov 10, 2026
8052698
chore: merge feat/breez-spark-lightning into feat/spark-emergency-exit
ovitrif Nov 10, 2026
01bfbd8
fix: cap the leftover sweep fee at bitkit's own rate
ovitrif Nov 10, 2026
2a203b4
fix: forget a savings payment only after three blocks unseen
ovitrif Nov 10, 2026
518bf31
chore: merge feat/breez-spark-lightning into feat/spark-emergency-exit
ovitrif Nov 11, 2026
6429e7b
fix: refuse a spark send once an exit holds spark
ovitrif Nov 11, 2026
270ae4c
fix: show spark exit funding amounts in bitcoin
ovitrif Nov 11, 2026
9a259f7
fix: keep counting what stays on spark during an exit
ovitrif Nov 11, 2026
246140b
fix: keep the valid generation over an unverified failed-only rebuild
ovitrif Nov 11, 2026
d840671
fix: never take a timelock reminder early without the tip
ovitrif Nov 11, 2026
b4a5944
fix: read a step already in the utxo set as accepted
ovitrif Nov 11, 2026
49cd36f
fix: stop driving a diverged generation during a top-up
ovitrif Nov 11, 2026
0dcda74
fix: keep the value of leaves the first build leaves behind
ovitrif Nov 11, 2026
267c8c9
fix: leave left-behind leaves out of the exit transfer
ovitrif Nov 11, 2026
8f724d9
fix: reconnect spark for a stalled exit
ovitrif Nov 11, 2026
599b963
fix: pay from savings only what the funding address lacks
ovitrif Nov 11, 2026
92c4f41
fix: drop a tapped exit notification with no result
ovitrif Nov 11, 2026
b619536
fix: report an exit that is no longer cancellable
ovitrif Nov 11, 2026
2ef82a8
fix: give a forgotten exit's funding address back
ovitrif Nov 11, 2026
5e21172
fix: delete the exit record's copies on wipe
ovitrif Nov 11, 2026
2fe70af
fix: show kept change recovery details once
ovitrif Nov 11, 2026
5f8e054
fix: cap the refused sweep rate on overflow
ovitrif Nov 11, 2026
f513443
fix: keep kept fee change's recovery details reachable
ovitrif Nov 11, 2026
d745ec9
fix: refuse an exit start while a spark send is still active
ovitrif Nov 11, 2026
9b4f8d1
fix: leave lost leaves out of what stays on spark during an exit
ovitrif Nov 11, 2026
39cb071
fix: count left-behind leaves on spark
ovitrif Nov 11, 2026
17f16d1
Merge branch 'feat/breez-spark-lightning' into feat/spark-emergency-exit
ovitrif Nov 11, 2026
f8c896b
fix: refresh wallet totals when the exit's amounts change
ovitrif Nov 11, 2026
27d38b3
Merge branch 'feat/breez-spark-lightning' into feat/spark-emergency-exit
ovitrif Nov 11, 2026
0c4fe37
fix: reject out-of-range fee estimates
ovitrif Nov 11, 2026
147a20f
fix: pay the extra input fee when savings completes funding
ovitrif Nov 11, 2026
c741a30
fix: reset seen funding when the funding address changes
ovitrif Nov 11, 2026
da07aa6
fix: count left-behind leaves in what stays on spark
ovitrif Nov 11, 2026
a13da47
fix: rebuild on redo while a top-up is awaited
ovitrif Nov 11, 2026
198b0b9
feat: keep earlier exit addresses reachable
ovitrif Nov 11, 2026
0c47124
fix: keep the valid generation when funding an unverified rebuild
ovitrif Nov 11, 2026
b085864
fix: withdraw an unverified rebuild's fee ask once its steps read again
ovitrif Nov 11, 2026
32ccd35
fix: keep the valid generation when a rebuild leaves a recovered leaf…
ovitrif Nov 11, 2026
a78786d
fix: keep the retry clock after an unverified rebuild that adopts not…
ovitrif Nov 11, 2026
cf3f96d
chore: merge feat/breez-spark-lightning into feat/spark-emergency-exit
ovitrif Nov 11, 2026
f0d06d9
fix: guard an unverified rebuild before saving it
ovitrif Nov 11, 2026
33766fb
fix: pay savings funding at least at the dust limit
ovitrif Nov 11, 2026
693c45a
fix: let a refused leftover sweep show once
ovitrif Nov 11, 2026
6e978ea
fix: read kept change at earlier exit addresses
ovitrif Nov 11, 2026
e728b65
docs: fix earlier exit address comments
ovitrif Nov 11, 2026
15b6925
fix: list kept change once its result was seen
ovitrif Nov 11, 2026
63a2f49
fix: keep addresses added during an earlier address refresh
ovitrif Nov 11, 2026
437a979
fix: guard every rebuild over a valid exit generation
ovitrif Nov 11, 2026
fd9c887
test: keep the valid generation after a leaf is left behind
ovitrif Nov 11, 2026
1af56fc
fix: pace a funded unverified resume once a block
ovitrif Nov 11, 2026
d8a058c
fix: show a final sweep refusal again after a foreground tick
ovitrif Nov 11, 2026
78cacc0
fix: keep reading kept change at a reused address
ovitrif Nov 11, 2026
5176fa0
fix: keep the valid generation over an unexitable leaf
ovitrif Nov 11, 2026
754725c
fix: read the configured regtest chain in the exit
ovitrif Nov 11, 2026
15f76ba
fix: fund the exit from savings only on spark's chain
ovitrif Nov 11, 2026
b72a025
Merge commit '18946a0f0' into HEAD
ovitrif Nov 11, 2026
7622b77
fix: back up the spark exit funding index
ovitrif Nov 11, 2026
fdfd7cd
fix: find the spark exit funding index after a restore without one
ovitrif Nov 11, 2026
9659b95
fix: back up the earlier spark exit addresses
ovitrif Nov 11, 2026
31be1fe
fix: watch earlier exits' funding that still holds coins after a restore
ovitrif Nov 11, 2026
793be4a
chore: merge the spark base into the spark exit branch
ovitrif Nov 11, 2026
9fab00f
fix: refuse a contact withdrawal while an exit runs
ovitrif Nov 11, 2026
e1dbb0b
fix: build a kept fee bump at its rate
ovitrif Nov 11, 2026
16b7c66
fix: pay a higher fee from savings only on spark's chain
ovitrif Nov 11, 2026
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
29 changes: 29 additions & 0 deletions Bitkit/AppScene.swift
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,35 @@ struct AppScene: View {
await pubkyProfile.retrySessionRestoration()
}
.task(id: [scenePhase == .active, network.isConnected, wipeCoordinator.isGateUp]) { await pollIncomingPaykitPaymentRequests() }
.task(id: [scenePhase == .active, SparkExitManager.shared.needsDriving]) {
guard scenePhase == .active else { return }
await SparkExitManager.shared.runWhileActive()
}
.task(id: [
SparkExitManager.shared.opensProgress,
SparkExitManager.shared.showsResult,
SparkExitManager.shared.hasLoadedRecord,
isLockedForDeepLinks,
wallet.walletExists == true,
]) {
// A tapped exit notification opens the exit once the wallet is unlocked and its record is loaded.
let exit = SparkExitManager.shared
guard exit.opensProgress, wallet.walletExists == true, !isLockedForDeepLinks else { return }
switch SparkExitManager.notificationOpen(
opensProgress: exit.opensProgress,
showsResult: exit.showsResult,
hasLoadedRecord: exit.hasLoadedRecord
) {
case .wait:
return
case .drop:
exit.opensProgress = false
case .open:
exit.opensProgress = false
navigation.reset()
navigation.navigate(.sparkExitProgress)
}
}
.task(id: foregroundContactSession) {
shopContactImport?.task.cancel()
shopContactImport = nil
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "hourglass-simple.pdf",
"filename" : "hourglass-simple.svg",
"idiom" : "universal"
}
],
Expand All @@ -10,6 +10,7 @@
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions Bitkit/BitkitApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool
{
UNUserNotificationCenter.current().delegate = self
SparkExitManager.registerBackgroundTask()

// Check notification authorization status at launch and re-register with APN if granted
UNUserNotificationCenter.current().getNotificationSettings { settings in
Expand Down Expand Up @@ -163,6 +164,8 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
PaykitSubscriptionNotificationTargetStore.save(target)
}
NotificationCenter.default.post(name: .paykitSubscriptionPaymentDue, object: nil, userInfo: userInfo)
} else if userInfo["bitkit_action"] as? String == SparkExitManager.notificationAction {
Task { @MainActor in SparkExitManager.shared.opensProgress = true }
} else {
PushNotificationManager.shared.handleNotification(userInfo)
}
Expand Down
21 changes: 21 additions & 0 deletions Bitkit/Constants/Env.swift
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,27 @@ enum Env {
.appendingPathComponent("wallet\(walletIndex)/spark-exit-restore.json")
}

/// The running Spark emergency exit, if any: its signed recovery and how far it got.
static func sparkExitRecord(walletIndex: Int) -> URL {
appStorageUrl
.appendingPathComponent(networkName)
.appendingPathComponent("wallet\(walletIndex)/spark-exit.json")
}

/// Earlier Spark exits' funding addresses that hold, or may still receive, coins, kept past the exit record.
static func sparkExitEarlierAddresses(walletIndex: Int) -> URL {
appStorageUrl
.appendingPathComponent(networkName)
.appendingPathComponent("wallet\(walletIndex)/spark-exit-earlier-addresses.json")
}

/// The leaves an older state of the wallet claimed in an earlier Spark exit, kept out of every later one.
static func sparkExitLostLeaves(walletIndex: Int) -> URL {
appStorageUrl
.appendingPathComponent(networkName)
.appendingPathComponent("wallet\(walletIndex)/spark-exit-lost-leaves.json")
}

/// Breez SDK API key, set with the `BREEZ_API_KEY` build setting. Spark on mainnet needs it; its regtest does not.
static var breezApiKey: String? {
infoPlistValue("BREEZ_API_KEY")
Expand Down
10 changes: 10 additions & 0 deletions Bitkit/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
<string>to.bitkit.spark-exit</string>
<string>to.bitkit.spark-exit.processing</string>
</array>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>processing</string>
</array>
<key>UIDesignRequiresCompatibility</key>
<true/>
<key>USDT_BRIDGE_NETWORKS</key>
Expand Down
6 changes: 6 additions & 0 deletions Bitkit/MainNavView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,12 @@ struct MainNavView: View {
case .connections: LightningConnectionsView()
case let .connectionDetail(channelId): LightningConnectionDetailView(channelId: channelId)
case .sparkConnectionDetail: SparkConnectionDetailView()
case .sparkExitIntro: SparkExitIntroView()
case .sparkExitQuote: SparkExitQuoteView()
case .sparkExitFunding: SparkExitFundingView()
case .sparkExitConfirm: SparkExitConfirmView()
case .sparkExitProgress: SparkExitProgressView()
case .sparkExitFeeBump: SparkExitFeeBumpView()
case let .closeConnection(channel: channel): CloseConnectionConfirmation(channel: channel)
case .node: NodeStateView()
case .electrumSettings: ElectrumSettingsScreen()
Expand Down
21 changes: 18 additions & 3 deletions Bitkit/Managers/BalanceManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ class BalanceManager {
/// Derives the complete balance state including pending transfers
/// - Returns: BalanceState with all balance calculations
/// - Throws: Error if balance retrieval fails
func deriveBalanceState() async throws -> BalanceState {
/// - Parameter exitInTransfer: the running Spark exit's transfer and what it still brings to savings, counted in
/// place of that transfer's fixed amount.
func deriveBalanceState(exitInTransfer: (transferId: String, sats: UInt64)? = nil) async throws -> BalanceState {
let balanceDetails = await MainActor.run { lightningService.balances }
guard let balanceDetails else {
throw AppError(message: "Balance details unavailable", debugMessage: "LightningService.balances is nil")
Expand All @@ -43,7 +45,8 @@ class BalanceManager {

let (lightningToSubtract, pendingCloseAmount) = await getCloseTransferAmounts(
transfers: activeTransfers,
balanceDetails: balanceDetails
balanceDetails: balanceDetails,
exitInTransfer: exitInTransfer
)

// Detect orphan closed channels: channels with lightning balance that are no longer
Expand Down Expand Up @@ -138,12 +141,18 @@ class BalanceManager {
/// - Returns: lightningToSubtract (always subtract from display), pendingAmount (add to total only if on-chain hasn't arrived)
private func getCloseTransferAmounts(
transfers: [Transfer],
balanceDetails: BalanceDetails
balanceDetails: BalanceDetails,
exitInTransfer: (transferId: String, sats: UInt64)? = nil
) async -> (lightningToSubtract: UInt64, pendingAmount: UInt64) {
var lightningToSubtract: UInt64 = 0
var pendingAmount: UInt64 = 0

for transfer in transfers.filter({ $0.type.isToSavings() }) {
// A Spark exit has no channel: it is in transfer until its sweep confirms and the exit settles it.
if transfer.type == .sparkExit {
pendingAmount += Self.sparkExitInTransferSats(transfer, exitInTransfer: exitInTransfer)
continue
}
guard let channelId = transfer.channelId else { continue }

let balanceFromLdk = balanceDetails.lightningBalances
Expand All @@ -165,6 +174,12 @@ class BalanceManager {
return (lightningToSubtract, pendingAmount)
}

/// The running exit's own transfer counts what it still brings to savings; any other exit transfer its amount.
static func sparkExitInTransferSats(_ transfer: Transfer, exitInTransfer: (transferId: String, sats: UInt64)?) -> UInt64 {
guard let exitInTransfer, exitInTransfer.transferId == transfer.id else { return transfer.amountSats }
return exitInTransfer.sats
}

/// Detects "orphan" closed channels - channels that have lightning balance in LDK
/// but are no longer in the channels list and don't have a Transfer record yet.
private func getOrphanClosedChannelBalance(
Expand Down
Loading
Loading