Skip to content

Commit 5c68064

Browse files
committed
fix: migrate activities for unsupported addresses
1 parent 820762c commit 5c68064

2 files changed

Lines changed: 104 additions & 21 deletions

File tree

app/src/main/java/to/bitkit/services/CoreService.kt

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,7 @@ class ActivityService(
600600
private fun buildUpdatedOnchainActivity(
601601
existingActivity: Activity.Onchain,
602602
confirmationData: ConfirmationData,
603+
ldkValue: ULong,
603604
channelId: String? = null,
604605
): OnchainActivity {
605606
var preservedIsTransfer = existingActivity.v1.isTransfer
@@ -612,13 +613,20 @@ class ActivityService(
612613

613614
val finalDoesExist = if (confirmationData.isConfirmed) true else existingActivity.v1.doesExist
614615

616+
val preservedValue = if (existingActivity.v1.value > ldkValue) {
617+
existingActivity.v1.value
618+
} else {
619+
ldkValue
620+
}
621+
615622
val updatedOnChain = existingActivity.v1.copy(
616623
confirmed = confirmationData.isConfirmed,
617624
confirmTimestamp = confirmationData.confirmedTimestamp,
618625
doesExist = finalDoesExist,
619626
updatedAt = confirmationData.timestamp,
620627
isTransfer = preservedIsTransfer,
621628
channelId = preservedChannelId,
629+
value = preservedValue,
622630
)
623631

624632
return updatedOnChain
@@ -667,10 +675,16 @@ class ActivityService(
667675
val timestamp = payment.latestUpdateTimestamp
668676
val confirmationData = getConfirmationStatus(kind, timestamp)
669677

670-
val existingActivity = getActivityById(payment.id)
678+
var existingActivity = getActivityById(payment.id)
679+
if (existingActivity == null) {
680+
getOnchainActivityByTxId(kind.txid)?.let {
681+
existingActivity = Activity.Onchain(it)
682+
}
683+
}
684+
671685
if (existingActivity != null &&
672686
existingActivity is Activity.Onchain &&
673-
(existingActivity.v1.updatedAt ?: 0u) > payment.latestUpdateTimestamp
687+
((existingActivity as Activity.Onchain).v1.updatedAt ?: 0u) > payment.latestUpdateTimestamp
674688
) {
675689
return
676690
}
@@ -691,10 +705,12 @@ class ActivityService(
691705

692706
val resolvedAddress = resolveAddressForInboundPayment(kind, existingActivity, payment, transactionDetails)
693707

708+
val ldkValue = payment.amountSats ?: 0u
694709
val onChain = if (existingActivity is Activity.Onchain) {
695710
buildUpdatedOnchainActivity(
696-
existingActivity = existingActivity,
711+
existingActivity = existingActivity as Activity.Onchain,
697712
confirmationData = confirmationData,
713+
ldkValue = ldkValue,
698714
channelId = resolvedChannelId,
699715
)
700716
} else {
@@ -713,7 +729,9 @@ class ActivityService(
713729
}
714730

715731
if (existingActivity != null) {
716-
updateActivity(payment.id, Activity.Onchain(onChain))
732+
val existingOnchain = (existingActivity as Activity.Onchain).v1
733+
// Update using the existing activity's id (may differ from payment.id for migrated activities)
734+
updateActivity(existingOnchain.id, Activity.Onchain(onChain))
717735
} else {
718736
upsertActivity(Activity.Onchain(onChain))
719737
}

app/src/main/java/to/bitkit/services/MigrationService.kt

Lines changed: 82 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,10 +1239,6 @@ class MigrationService @Inject constructor(
12391239
if (hasRNMmkvData()) {
12401240
val mmkvData = loadRNMmkvData() ?: return
12411241

1242-
extractRNMetadata(mmkvData)?.let { metadata ->
1243-
applyRNMetadata(metadata)
1244-
}
1245-
12461242
extractRNActivities(mmkvData)?.let { activities ->
12471243
applyOnchainMetadata(activities)
12481244
}
@@ -1257,6 +1253,10 @@ class MigrationService @Inject constructor(
12571253
applyBoostTransactions(boosts)
12581254
}
12591255
}
1256+
1257+
extractRNMetadata(mmkvData)?.let { metadata ->
1258+
applyRNMetadata(metadata)
1259+
}
12601260
}
12611261

12621262
pendingRemoteActivityData?.let { remoteActivities ->
@@ -1450,6 +1450,21 @@ class MigrationService @Inject constructor(
14501450
}
14511451
}
14521452

1453+
// Preserve higher value from backup (handles mixed input txs with unsupported addresses)
1454+
val backupValue = item.value.toULong()
1455+
if (backupValue > updated.value) {
1456+
updated = updated.copy(value = backupValue)
1457+
wasUpdated = true
1458+
}
1459+
1460+
// Preserve higher fee from backup
1461+
item.fee?.let { backupFee ->
1462+
if (backupFee.toULong() > updated.fee) {
1463+
updated = updated.copy(fee = backupFee.toULong())
1464+
wasUpdated = true
1465+
}
1466+
}
1467+
14531468
item.address?.let { address ->
14541469
if (address.isNotEmpty() && updated.address != address) {
14551470
updated = updated.copy(address = address)
@@ -1460,30 +1475,80 @@ class MigrationService @Inject constructor(
14601475
return if (wasUpdated) updated else null
14611476
}
14621477

1463-
@Suppress("CyclomaticComplexMethod", "NestedBlockDepth")
1478+
@Suppress("CyclomaticComplexMethod", "NestedBlockDepth", "LongMethod")
14641479
private suspend fun applyOnchainMetadata(items: List<RNActivityItem>) {
14651480
val onchainItems = items.filter { it.activityType == "onchain" }
1481+
var updatedCount = 0
1482+
var createdCount = 0
14661483

14671484
onchainItems.forEach { item ->
14681485
val txId = item.txId ?: item.id.takeIf { it.isNotEmpty() } ?: return@forEach
14691486

14701487
val onchain = activityRepo.getOnchainActivityByTxId(txId)
1471-
if (onchain == null) {
1472-
Logger.warn("Onchain activity not found for txId: $txId", context = TAG)
1473-
return@forEach
1474-
}
1488+
if (onchain != null) {
1489+
// Activity exists, update it with metadata from backup
1490+
updateOnchainActivityMetadata(item, onchain)?.let { updated ->
1491+
activityRepo.updateActivity(updated.id, Activity.Onchain(updated))
1492+
.onSuccess { updatedCount++ }
1493+
.onFailure { e ->
1494+
Logger.error(
1495+
"Failed to update onchain activity metadata for $txId: $e",
1496+
e,
1497+
context = TAG
1498+
)
1499+
}
1500+
}
1501+
} else {
1502+
val timestampSecs = (item.timestamp / MS_PER_SEC).toULong()
1503+
val now = (System.currentTimeMillis() / MS_PER_SEC).toULong()
14751504

1476-
updateOnchainActivityMetadata(item, onchain)?.let { updated ->
1477-
activityRepo.updateActivity(updated.id, Activity.Onchain(updated))
1478-
.onFailure { e ->
1479-
Logger.error(
1480-
"Failed to update onchain activity metadata for $txId: $e",
1481-
e,
1482-
context = TAG
1483-
)
1505+
val activityTimestamp = if (timestampSecs > 0u) timestampSecs else now
1506+
1507+
val newOnchain = OnchainActivity(
1508+
id = item.id,
1509+
txType = if (item.txType == "sent") PaymentType.SENT else PaymentType.RECEIVED,
1510+
txId = txId,
1511+
value = item.value.toULong(),
1512+
fee = (item.fee ?: 0).toULong(),
1513+
feeRate = (item.feeRate ?: 1).toULong(),
1514+
address = item.address ?: "",
1515+
timestamp = activityTimestamp,
1516+
confirmed = item.confirmed ?: false,
1517+
isBoosted = item.isBoosted ?: false,
1518+
boostTxIds = emptyList(),
1519+
isTransfer = item.isTransfer ?: false,
1520+
confirmTimestamp = item.confirmTimestamp?.let { (it / MS_PER_SEC).toULong() },
1521+
channelId = item.channelId,
1522+
transferTxId = item.transferTxId,
1523+
doesExist = item.exists ?: true,
1524+
createdAt = activityTimestamp,
1525+
updatedAt = activityTimestamp,
1526+
seenAt = now,
1527+
)
1528+
1529+
runCatching {
1530+
activityRepo.upsertActivity(Activity.Onchain(newOnchain))
1531+
createdCount++
1532+
1533+
item.boostedParents?.takeIf { it.isNotEmpty() }?.let { parents ->
1534+
applyBoostedParents(parents, txId)
14841535
}
1536+
}.onFailure { e ->
1537+
Logger.error(
1538+
"Failed to create onchain activity for unsupported address $txId: $e",
1539+
e,
1540+
context = TAG
1541+
)
1542+
}
14851543
}
14861544
}
1545+
1546+
if (updatedCount > 0 || createdCount > 0) {
1547+
Logger.info(
1548+
"Applied metadata to $updatedCount onchain activities, created $createdCount for unsupported addresses",
1549+
context = TAG
1550+
)
1551+
}
14871552
}
14881553

14891554
@Suppress("LongMethod", "CyclomaticComplexMethod", "NestedBlockDepth")

0 commit comments

Comments
 (0)