Skip to content

Commit 428e242

Browse files
committed
fix: migrate activities for unsupported addresses
1 parent 635f4f6 commit 428e242

File tree

2 files changed

+125
-56
lines changed

2 files changed

+125
-56
lines changed

Bitkit/Services/CoreService.swift

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,12 @@ class ActivityService {
338338
guard case let .onchain(txid, _) = payment.kind else { return }
339339

340340
let paymentTimestamp = payment.latestUpdateTimestamp
341-
let existingActivity = try getActivityById(activityId: payment.id)
341+
342+
// Look for existing activity by id first, then by txid (for migrated activities)
343+
var existingActivity = try getActivityById(activityId: payment.id)
344+
if existingActivity == nil {
345+
existingActivity = try BitkitCore.getActivityByTxId(txId: txid).map { .onchain($0) }
346+
}
342347

343348
// Skip if existing activity has newer timestamp to avoid overwriting local data
344349
if let existingActivity, case let .onchain(existing) = existingActivity {
@@ -348,9 +353,6 @@ class ActivityService {
348353
}
349354
}
350355

351-
// Determine confirmation status from payment's txStatus
352-
let value = payment.amountSats ?? 0
353-
354356
// Determine confirmation status from payment's txStatus
355357
var blockTimestamp: UInt64?
356358
let isConfirmed: Bool
@@ -381,6 +383,13 @@ class ActivityService {
381383
let doesExist = existingOnchain?.doesExist ?? true
382384
let seenAt = existingOnchain?.seenAt
383385

386+
let ldkValue = payment.amountSats ?? 0
387+
let value: UInt64 = if let existingValue = existingOnchain?.value, existingValue > ldkValue {
388+
existingValue
389+
} else {
390+
ldkValue
391+
}
392+
384393
// Check if this transaction is a channel transfer
385394
if channelId == nil || !isTransfer {
386395
let foundChannelId = await findChannelForTransaction(
@@ -441,8 +450,8 @@ class ActivityService {
441450
seenAt: seenAt
442451
)
443452

444-
if existingActivity != nil {
445-
try await update(id: payment.id, activity: .onchain(onchain))
453+
if let existingActivity, case let .onchain(existing) = existingActivity {
454+
try await update(id: existing.id, activity: .onchain(onchain))
446455
} else {
447456
try await upsert(.onchain(onchain))
448457
}

Bitkit/Services/MigrationsService.swift

Lines changed: 110 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,11 +1200,6 @@ extension MigrationsService {
12001200
func reapplyMetadataAfterSync() async {
12011201
// Handle MMKV (local) migration data
12021202
if hasRNMmkvData(), let mmkvData = loadRNMmkvData() {
1203-
if let metadata = extractRNMetadata(from: mmkvData) {
1204-
Logger.info("Re-applying MMKV metadata after sync", context: "Migration")
1205-
await applyAllMetadata(metadata)
1206-
}
1207-
12081203
if let activities = extractRNActivities(from: mmkvData) {
12091204
await applyOnchainMetadata(activities)
12101205
}
@@ -1220,6 +1215,11 @@ extension MigrationsService {
12201215
await applyBoostTransactions(walletBackup.boosts)
12211216
}
12221217
}
1218+
1219+
if let metadata = extractRNMetadata(from: mmkvData) {
1220+
Logger.info("Re-applying MMKV metadata after sync", context: "Migration")
1221+
await applyAllMetadata(metadata)
1222+
}
12231223
}
12241224

12251225
// Handle remote backup data (for on-chain timestamps from RN backup)
@@ -1243,7 +1243,7 @@ extension MigrationsService {
12431243
pendingRemoteBoosts = nil
12441244
}
12451245

1246-
// Apply stored metadata (all tags after sync when activities exist)
1246+
// Apply stored metadata (all tags after activities are imported)
12471247
if let metadata = pendingRemoteMetadata {
12481248
Logger.info("Applying stored metadata after sync", context: "Migration")
12491249
await applyAllMetadata(metadata)
@@ -1374,63 +1374,123 @@ extension MigrationsService {
13741374

13751375
private func applyOnchainMetadata(_ items: [RNActivityItem]) async {
13761376
let onchainItems = items.filter { $0.activityType == "onchain" }
1377+
var updatedCount = 0
1378+
var createdCount = 0
1379+
13771380
for item in onchainItems {
1378-
guard let txId = item.txId ?? (item.id.isEmpty ? nil : item.id),
1379-
var onchain = try? await CoreService.shared.activity.getOnchainActivityByTxId(txid: txId)
1380-
else {
1381+
guard let txId = item.txId ?? (item.id.isEmpty ? nil : item.id) else {
13811382
continue
13821383
}
13831384

1384-
if item.timestamp > 0 {
1385-
onchain.timestamp = UInt64(item.timestamp / 1000)
1386-
}
1387-
if let confirmTs = item.confirmTimestamp, confirmTs > 0 {
1388-
onchain.confirmTimestamp = UInt64(confirmTs / 1000)
1389-
}
1390-
if item.isTransfer == true {
1391-
onchain.isTransfer = true
1392-
onchain.channelId = item.channelId
1393-
onchain.transferTxId = item.transferTxId
1394-
}
1385+
// Try to get existing activity (synced by LDK)
1386+
if var onchain = try? await CoreService.shared.activity.getOnchainActivityByTxId(txid: txId) {
1387+
// Activity exists, update metadata
1388+
if item.timestamp > 0 {
1389+
onchain.timestamp = UInt64(item.timestamp / 1000)
1390+
}
1391+
if let confirmTs = item.confirmTimestamp, confirmTs > 0 {
1392+
onchain.confirmTimestamp = UInt64(confirmTs / 1000)
1393+
}
1394+
if item.isTransfer == true {
1395+
onchain.isTransfer = true
1396+
onchain.channelId = item.channelId
1397+
onchain.transferTxId = item.transferTxId
1398+
}
13951399

1396-
if let boostedParents = item.boostedParents, !boostedParents.isEmpty {
1397-
for parentTxId in boostedParents {
1398-
if var parentOnchain = try? await CoreService.shared.activity.getOnchainActivityByTxId(txid: parentTxId) {
1399-
if !parentOnchain.boostTxIds.contains(txId) {
1400-
parentOnchain.boostTxIds.append(txId)
1401-
}
1402-
parentOnchain.isBoosted = true
1400+
if let boostedParents = item.boostedParents, !boostedParents.isEmpty {
1401+
await applyBoostedParents(boostedParents, childTxId: txId)
1402+
onchain.isBoosted = false
1403+
onchain.boostTxIds.removeAll { boostedParents.contains($0) }
1404+
} else if item.isBoosted == true {
1405+
onchain.isBoosted = true
1406+
}
14031407

1404-
do {
1405-
try await CoreService.shared.activity.update(id: parentOnchain.id, activity: .onchain(parentOnchain))
1406-
} catch {
1407-
Logger.error("Failed to mark parent \(parentTxId) as boosted for CPFP: \(error)", context: "Migration")
1408-
}
1409-
}
1408+
if let feeRate = item.feeRate, feeRate > 0 {
1409+
onchain.feeRate = UInt64(feeRate)
14101410
}
1411-
onchain.isBoosted = false
1412-
onchain.boostTxIds.removeAll { boostedParents.contains($0) }
1413-
} else if item.isBoosted == true {
1414-
onchain.isBoosted = true
1415-
}
14161411

1417-
if let feeRate = item.feeRate, feeRate > 0 {
1418-
onchain.feeRate = UInt64(feeRate)
1419-
}
1412+
// Preserve higher value from backup (handles mixed input txs with unsupported addresses)
1413+
let backupValue = UInt64(item.value)
1414+
if backupValue > onchain.value {
1415+
onchain.value = backupValue
1416+
}
14201417

1421-
if let address = item.address, !address.isEmpty {
1422-
onchain.address = address
1423-
}
1418+
// Preserve higher fee from backup
1419+
if let backupFee = item.fee, UInt64(backupFee) > onchain.fee {
1420+
onchain.fee = UInt64(backupFee)
1421+
}
14241422

1425-
do {
1426-
try await CoreService.shared.activity.update(id: onchain.id, activity: .onchain(onchain))
1427-
} catch {
1428-
Logger.error("Failed to update onchain metadata for \(txId): \(error)", context: "Migration")
1423+
if let address = item.address, !address.isEmpty {
1424+
onchain.address = address
1425+
}
1426+
1427+
do {
1428+
try await CoreService.shared.activity.update(id: onchain.id, activity: .onchain(onchain))
1429+
updatedCount += 1
1430+
} catch {
1431+
Logger.error("Failed to update onchain metadata for \(txId): \(error)", context: "Migration")
1432+
}
1433+
} else {
1434+
let timestampSecs = UInt64(item.timestamp / 1000)
1435+
let now = UInt64(Date().timeIntervalSince1970)
1436+
let activityTimestamp = timestampSecs > 0 ? timestampSecs : now
1437+
1438+
let onchain = BitkitCore.OnchainActivity(
1439+
id: item.id,
1440+
txType: item.txType == "sent" ? .sent : .received,
1441+
txId: txId,
1442+
value: UInt64(item.value),
1443+
fee: item.fee.map { UInt64($0) } ?? 0,
1444+
feeRate: item.feeRate.map { UInt64($0) } ?? 1,
1445+
address: item.address ?? "",
1446+
confirmed: item.confirmed ?? false,
1447+
timestamp: activityTimestamp,
1448+
isBoosted: item.isBoosted ?? false,
1449+
boostTxIds: [],
1450+
isTransfer: item.isTransfer ?? false,
1451+
doesExist: item.exists ?? true,
1452+
confirmTimestamp: item.confirmTimestamp.map { UInt64($0 / 1000) },
1453+
channelId: item.channelId,
1454+
transferTxId: item.transferTxId,
1455+
createdAt: activityTimestamp,
1456+
updatedAt: activityTimestamp,
1457+
seenAt: now
1458+
)
1459+
1460+
do {
1461+
try await CoreService.shared.activity.upsert(.onchain(onchain))
1462+
createdCount += 1
1463+
1464+
if let boostedParents = item.boostedParents, !boostedParents.isEmpty {
1465+
await applyBoostedParents(boostedParents, childTxId: txId)
1466+
}
1467+
} catch {
1468+
Logger.error("Failed to import onchain activity from backup \(txId): \(error)", context: "Migration")
1469+
}
14291470
}
14301471
}
14311472

1432-
if !onchainItems.isEmpty {
1433-
Logger.info("Applied metadata to \(onchainItems.count) onchain activities", context: "Migration")
1473+
if updatedCount > 0 || createdCount > 0 {
1474+
Logger.info(
1475+
"Applied metadata to \(updatedCount) onchain activities, imported \(createdCount) from backup",
1476+
context: "Migration"
1477+
)
1478+
}
1479+
}
1480+
1481+
private func applyBoostedParents(_ boostedParents: [String], childTxId: String) async {
1482+
for parentTxId in boostedParents {
1483+
if var parentOnchain = try? await CoreService.shared.activity.getOnchainActivityByTxId(txid: parentTxId) {
1484+
if !parentOnchain.boostTxIds.contains(childTxId) {
1485+
parentOnchain.boostTxIds.append(childTxId)
1486+
}
1487+
parentOnchain.isBoosted = true
1488+
do {
1489+
try await CoreService.shared.activity.update(id: parentOnchain.id, activity: .onchain(parentOnchain))
1490+
} catch {
1491+
Logger.error("Failed to mark parent \(parentTxId) as boosted for CPFP: \(error)", context: "Migration")
1492+
}
1493+
}
14341494
}
14351495
}
14361496

0 commit comments

Comments
 (0)