Skip to content

Commit bccb5fe

Browse files
committed
Merge branch 'feat/multiple-addresses-types' of https://github.com/synonymdev/bitkit-ios into feat/multiple-addresses-types
2 parents 201817b + 70457e1 commit bccb5fe

3 files changed

Lines changed: 58 additions & 3 deletions

File tree

Bitkit/Services/MigrationsService.swift

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ class MigrationsService: ObservableObject {
338338
private static let rnPendingChannelMigrationKey = "rnPendingChannelMigration"
339339
private static let rnPendingBlocktankOrderIdsKey = "rnPendingBlocktankOrderIds"
340340
private static let rnDidAttemptPeerRecoveryKey = "rnDidAttemptMigrationPeerRecovery"
341+
private static let didCleanupInvalidTransfersKey = "didCleanupInvalidMigrationTransfers"
341342

342343
@Published var isShowingMigrationLoading = false {
343344
didSet {
@@ -761,6 +762,47 @@ extension MigrationsService {
761762
return true
762763
}
763764

765+
/// One-time cleanup for transfers created from unpaid/expired Blocktank orders during migration.
766+
/// The RN backup's paidOrders map could contain orders that were never actually paid.
767+
func cleanupInvalidMigrationTransfers() async {
768+
guard !UserDefaults.standard.bool(forKey: Self.didCleanupInvalidTransfersKey) else { return }
769+
guard rnMigrationCompleted else { return }
770+
771+
guard let transfers = try? TransferStorage.shared.getActiveTransfers() else { return }
772+
let orderTransfers = transfers.filter { $0.type.isToSpending() && $0.lspOrderId != nil }
773+
774+
guard !orderTransfers.isEmpty else {
775+
UserDefaults.standard.set(true, forKey: Self.didCleanupInvalidTransfersKey)
776+
return
777+
}
778+
779+
let orderIds = orderTransfers.compactMap(\.lspOrderId)
780+
781+
guard let orders = try? await CoreService.shared.blocktank.orders(orderIds: orderIds, filter: nil, refresh: true) else {
782+
// Don't mark as done if we can't reach Blocktank — retry next launch
783+
Logger.warn("Cannot cleanup migration transfers: Blocktank unreachable", context: "Migration")
784+
return
785+
}
786+
787+
let now = UInt64(Date().timeIntervalSince1970)
788+
for transfer in orderTransfers {
789+
guard let orderId = transfer.lspOrderId,
790+
let order = orders.first(where: { $0.id == orderId })
791+
else { continue }
792+
793+
if order.state2 != .paid {
794+
try? TransferStorage.shared.markSettled(id: transfer.id, settledAt: now)
795+
Logger.info(
796+
"Cleanup: settled invalid migration transfer \(transfer.id) for order \(orderId) (state: \(order.state2))",
797+
context: "Migration"
798+
)
799+
}
800+
}
801+
802+
UserDefaults.standard.set(true, forKey: Self.didCleanupInvalidTransfersKey)
803+
Logger.info("Migration transfer cleanup completed", context: "Migration")
804+
}
805+
764806
/// Clears all persisted pending migration data from UserDefaults
765807
private func clearPendingMigrationData() {
766808
pendingChannelMigration = nil
@@ -2372,14 +2414,16 @@ extension MigrationsService {
23722414
continue
23732415
}
23742416

2375-
if order.state2 == .executed {
2417+
// Only create transfers for orders actually paid and awaiting channel
2418+
guard order.state2 == .paid else {
2419+
Logger.debug("Skipping order \(orderId) with state \(order.state2) for transfer creation", context: "Migration")
23762420
continue
23772421
}
23782422

23792423
let transfer = Transfer(
23802424
id: txId,
23812425
type: .toSpending,
2382-
amountSats: order.clientBalanceSat + order.feeSat,
2426+
amountSats: order.clientBalanceSat,
23832427
channelId: nil,
23842428
fundingTxId: nil,
23852429
lspOrderId: orderId,

Bitkit/Services/TransferService.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,17 @@ class TransferService {
135135
Logger.debug("Channel \(channelId) exists but not yet usable for transfer: \(transfer.id)", context: "TransferService")
136136
}
137137
} else {
138-
// No channel ID resolved - check if we should timeout this transfer
138+
// No channel ID resolved - check if order is expired/terminal
139+
if let orderId = transfer.lspOrderId {
140+
if let orders = try? await blocktankService.orders(orderIds: [orderId], filter: nil, refresh: false),
141+
let order = orders.first,
142+
order.state2 == .expired
143+
{
144+
try await markSettled(id: transfer.id)
145+
Logger.info("Order \(orderId) expired, settled transfer: \(transfer.id)", context: "TransferService")
146+
continue
147+
}
148+
}
139149
Logger.debug(
140150
"Could not resolve channel for transfer: \(transfer.id) orderId: \(transfer.lspOrderId ?? "none")",
141151
context: "TransferService"

Bitkit/ViewModels/WalletViewModel.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,7 @@ class WalletViewModel: ObservableObject {
683683
await lightningService.refreshCache()
684684

685685
do {
686+
await MigrationsService.shared.cleanupInvalidMigrationTransfers()
686687
try? await transferService.syncTransferStates()
687688
let state = try await balanceManager.deriveBalanceState()
688689
balanceInTransferToSavings = Int(state.balanceInTransferToSavings)

0 commit comments

Comments
 (0)