diff --git a/app/src/main/java/to/bitkit/services/CoreService.kt b/app/src/main/java/to/bitkit/services/CoreService.kt index 441357454..0fd0ca82d 100644 --- a/app/src/main/java/to/bitkit/services/CoreService.kt +++ b/app/src/main/java/to/bitkit/services/CoreService.kt @@ -600,6 +600,7 @@ class ActivityService( private fun buildUpdatedOnchainActivity( existingActivity: Activity.Onchain, confirmationData: ConfirmationData, + ldkValue: ULong, channelId: String? = null, ): OnchainActivity { var preservedIsTransfer = existingActivity.v1.isTransfer @@ -612,6 +613,12 @@ class ActivityService( val finalDoesExist = if (confirmationData.isConfirmed) true else existingActivity.v1.doesExist + val preservedValue = if (existingActivity.v1.value > ldkValue) { + existingActivity.v1.value + } else { + ldkValue + } + val updatedOnChain = existingActivity.v1.copy( confirmed = confirmationData.isConfirmed, confirmTimestamp = confirmationData.confirmedTimestamp, @@ -619,6 +626,7 @@ class ActivityService( updatedAt = confirmationData.timestamp, isTransfer = preservedIsTransfer, channelId = preservedChannelId, + value = preservedValue, ) return updatedOnChain @@ -667,10 +675,16 @@ class ActivityService( val timestamp = payment.latestUpdateTimestamp val confirmationData = getConfirmationStatus(kind, timestamp) - val existingActivity = getActivityById(payment.id) + var existingActivity = getActivityById(payment.id) + if (existingActivity == null) { + getOnchainActivityByTxId(kind.txid)?.let { + existingActivity = Activity.Onchain(it) + } + } + if (existingActivity != null && existingActivity is Activity.Onchain && - (existingActivity.v1.updatedAt ?: 0u) > payment.latestUpdateTimestamp + ((existingActivity as Activity.Onchain).v1.updatedAt ?: 0u) > payment.latestUpdateTimestamp ) { return } @@ -691,10 +705,12 @@ class ActivityService( val resolvedAddress = resolveAddressForInboundPayment(kind, existingActivity, payment, transactionDetails) + val ldkValue = payment.amountSats ?: 0u val onChain = if (existingActivity is Activity.Onchain) { buildUpdatedOnchainActivity( - existingActivity = existingActivity, + existingActivity = existingActivity as Activity.Onchain, confirmationData = confirmationData, + ldkValue = ldkValue, channelId = resolvedChannelId, ) } else { @@ -712,8 +728,9 @@ class ActivityService( return } - if (existingActivity != null) { - updateActivity(payment.id, Activity.Onchain(onChain)) + if (existingActivity != null && existingActivity is Activity.Onchain) { + val existingOnchain = existingActivity.v1 + updateActivity(existingOnchain.id, Activity.Onchain(onChain)) } else { upsertActivity(Activity.Onchain(onChain)) } diff --git a/app/src/main/java/to/bitkit/services/MigrationService.kt b/app/src/main/java/to/bitkit/services/MigrationService.kt index fbb8df10d..068b4c5a8 100644 --- a/app/src/main/java/to/bitkit/services/MigrationService.kt +++ b/app/src/main/java/to/bitkit/services/MigrationService.kt @@ -1239,10 +1239,6 @@ class MigrationService @Inject constructor( if (hasRNMmkvData()) { val mmkvData = loadRNMmkvData() ?: return - extractRNMetadata(mmkvData)?.let { metadata -> - applyRNMetadata(metadata) - } - extractRNActivities(mmkvData)?.let { activities -> applyOnchainMetadata(activities) } @@ -1257,6 +1253,10 @@ class MigrationService @Inject constructor( applyBoostTransactions(boosts) } } + + extractRNMetadata(mmkvData)?.let { metadata -> + applyRNMetadata(metadata) + } } pendingRemoteActivityData?.let { remoteActivities -> @@ -1450,6 +1450,19 @@ class MigrationService @Inject constructor( } } + val backupValue = item.value.toULong() + if (backupValue > updated.value) { + updated = updated.copy(value = backupValue) + wasUpdated = true + } + + item.fee?.let { backupFee -> + if (backupFee.toULong() > updated.fee) { + updated = updated.copy(fee = backupFee.toULong()) + wasUpdated = true + } + } + item.address?.let { address -> if (address.isNotEmpty() && updated.address != address) { updated = updated.copy(address = address) @@ -1460,30 +1473,80 @@ class MigrationService @Inject constructor( return if (wasUpdated) updated else null } - @Suppress("CyclomaticComplexMethod", "NestedBlockDepth") + @Suppress("CyclomaticComplexMethod", "NestedBlockDepth", "LongMethod") private suspend fun applyOnchainMetadata(items: List) { val onchainItems = items.filter { it.activityType == "onchain" } + var updatedCount = 0 + var createdCount = 0 onchainItems.forEach { item -> val txId = item.txId ?: item.id.takeIf { it.isNotEmpty() } ?: return@forEach val onchain = activityRepo.getOnchainActivityByTxId(txId) - if (onchain == null) { - Logger.warn("Onchain activity not found for txId: $txId", context = TAG) - return@forEach - } + if (onchain != null) { + updateOnchainActivityMetadata(item, onchain)?.let { updated -> + activityRepo.updateActivity(updated.id, Activity.Onchain(updated)) + .onSuccess { updatedCount++ } + .onFailure { e -> + Logger.error( + "Failed to update onchain activity metadata for $txId: $e", + e, + context = TAG + ) + } + } + } else { + val timestampSecs = (item.timestamp / MS_PER_SEC).toULong() + val now = (System.currentTimeMillis() / MS_PER_SEC).toULong() - updateOnchainActivityMetadata(item, onchain)?.let { updated -> - activityRepo.updateActivity(updated.id, Activity.Onchain(updated)) + val activityTimestamp = if (timestampSecs > 0u) timestampSecs else now + + val newOnchain = OnchainActivity( + id = item.id, + txType = if (item.txType == "sent") PaymentType.SENT else PaymentType.RECEIVED, + txId = txId, + value = item.value.toULong(), + fee = (item.fee ?: 0).toULong(), + feeRate = (item.feeRate ?: 1).toULong(), + address = item.address ?: "", + timestamp = activityTimestamp, + confirmed = item.confirmed ?: false, + isBoosted = item.isBoosted ?: false, + boostTxIds = emptyList(), + isTransfer = item.isTransfer ?: false, + confirmTimestamp = item.confirmTimestamp?.let { (it / MS_PER_SEC).toULong() }, + channelId = item.channelId, + transferTxId = item.transferTxId, + doesExist = item.exists ?: true, + createdAt = activityTimestamp, + updatedAt = activityTimestamp, + seenAt = now, + ) + + activityRepo.upsertActivity(Activity.Onchain(newOnchain)) + .onSuccess { + createdCount++ + + item.boostedParents?.takeIf { it.isNotEmpty() }?.let { parents -> + applyBoostedParents(parents, txId) + } + } .onFailure { e -> Logger.error( - "Failed to update onchain activity metadata for $txId: $e", + "Failed to create onchain activity for unsupported address $txId: $e", e, context = TAG ) } } } + + if (updatedCount > 0 || createdCount > 0) { + Logger.info( + "Applied metadata to $updatedCount onchain activities, created $createdCount for unsupported addresses", + context = TAG + ) + } } @Suppress("LongMethod", "CyclomaticComplexMethod", "NestedBlockDepth")