From 241853101d326a38417d2a1ba544ad831e3c7ed5 Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Mon, 6 Oct 2025 13:49:14 -0300 Subject: [PATCH 1/4] fix: create cjit order --- .../java/to/bitkit/viewmodels/AppViewModel.kt | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt b/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt index 44b343d5f..4ee6fa86b 100644 --- a/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt +++ b/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt @@ -11,14 +11,17 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import androidx.navigation.NavOptions import androidx.navigation.navOptions +import com.synonym.bitkitcore.Activity import com.synonym.bitkitcore.ActivityFilter import com.synonym.bitkitcore.FeeRates +import com.synonym.bitkitcore.LightningActivity import com.synonym.bitkitcore.LightningInvoice import com.synonym.bitkitcore.LnurlAuthData import com.synonym.bitkitcore.LnurlChannelData import com.synonym.bitkitcore.LnurlPayData import com.synonym.bitkitcore.LnurlWithdrawData import com.synonym.bitkitcore.OnChainInvoice +import com.synonym.bitkitcore.PaymentState import com.synonym.bitkitcore.PaymentType import com.synonym.bitkitcore.Scanner import com.synonym.bitkitcore.decode @@ -54,12 +57,14 @@ import to.bitkit.di.BgDispatcher import to.bitkit.env.Env import to.bitkit.ext.WatchResult import to.bitkit.ext.amountOnClose +import to.bitkit.ext.amountSats import to.bitkit.ext.getClipboardText import to.bitkit.ext.getSatsPerVByteFor import to.bitkit.ext.maxSendableSat import to.bitkit.ext.maxWithdrawableSat import to.bitkit.ext.minSendableSat import to.bitkit.ext.minWithdrawableSat +import to.bitkit.ext.nowTimestamp import to.bitkit.ext.rawId import to.bitkit.ext.removeSpaces import to.bitkit.ext.setClipboardText @@ -222,14 +227,33 @@ class AppViewModel @Inject constructor( is Event.ChannelReady -> { val channel = lightningRepo.getChannels()?.find { it.channelId == event.channelId } if (channel != null && blocktankRepo.isCjitOrder(channel)) { + val amount = channel.amountOnClose.toLong() showNewTransactionSheet( NewTransactionSheetDetails( type = NewTransactionSheetType.LIGHTNING, direction = NewTransactionSheetDirection.RECEIVED, - sats = channel.amountOnClose.toLong(), + sats = amount, ), event = event ) + val now = nowTimestamp().toEpochMilli().toULong() + activityRepo.insertActivity( + Activity.Lightning( + LightningActivity( + id = channel.fundingTxo?.txid.orEmpty(), + txType = PaymentType.RECEIVED, + status = PaymentState.SUCCEEDED, + value = amount.toULong(), + fee = 0U, + invoice = "Loading...", // todo + message = "", + timestamp = now, + preimage = null, + createdAt = now, + updatedAt = null, + ) + ) + ) } else { toast( type = Toast.ToastType.LIGHTNING, From 4e2b61f9d46d369db253f8d5c62204c209dde3d6 Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Mon, 6 Oct 2025 19:32:26 -0300 Subject: [PATCH 2/4] feat: get cjit order invoice --- .../java/to/bitkit/repositories/BlocktankRepo.kt | 12 +++++------- .../main/java/to/bitkit/viewmodels/AppViewModel.kt | 6 +++--- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/to/bitkit/repositories/BlocktankRepo.kt b/app/src/main/java/to/bitkit/repositories/BlocktankRepo.kt index ac5f9b943..f485dce01 100644 --- a/app/src/main/java/to/bitkit/repositories/BlocktankRepo.kt +++ b/app/src/main/java/to/bitkit/repositories/BlocktankRepo.kt @@ -97,13 +97,11 @@ class BlocktankRepo @Inject constructor( } } - suspend fun isCjitOrder(channel: ChannelDetails): Boolean = withContext(bgDispatcher) { - return@withContext runCatching { - _blocktankState.value.cjitEntries.any { order -> - order.channelSizeSat == channel.channelValueSats && - order.lspNode.pubkey == channel.counterpartyNodeId - } - }.getOrDefault(false) + suspend fun getCjitOrder(channel: ChannelDetails): IcJitEntry? = withContext(bgDispatcher) { + return@withContext _blocktankState.value.cjitEntries.firstOrNull { order -> + order.channelSizeSat == channel.channelValueSats && + order.lspNode.pubkey == channel.counterpartyNodeId + } } suspend fun refreshInfo() = withContext(bgDispatcher) { diff --git a/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt b/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt index 4ee6fa86b..1c50baeec 100644 --- a/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt +++ b/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt @@ -57,7 +57,6 @@ import to.bitkit.di.BgDispatcher import to.bitkit.env.Env import to.bitkit.ext.WatchResult import to.bitkit.ext.amountOnClose -import to.bitkit.ext.amountSats import to.bitkit.ext.getClipboardText import to.bitkit.ext.getSatsPerVByteFor import to.bitkit.ext.maxSendableSat @@ -226,7 +225,8 @@ class AppViewModel @Inject constructor( is Event.ChannelReady -> { val channel = lightningRepo.getChannels()?.find { it.channelId == event.channelId } - if (channel != null && blocktankRepo.isCjitOrder(channel)) { + val cjitOrder = channel?.let { blocktankRepo.getCjitOrder(it) } + if (cjitOrder != null) { val amount = channel.amountOnClose.toLong() showNewTransactionSheet( NewTransactionSheetDetails( @@ -245,7 +245,7 @@ class AppViewModel @Inject constructor( status = PaymentState.SUCCEEDED, value = amount.toULong(), fee = 0U, - invoice = "Loading...", // todo + invoice = cjitOrder.invoice.request, message = "", timestamp = now, preimage = null, From 90b248b9371d808f1377ee3256a1c44607f70969 Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Mon, 6 Oct 2025 19:48:43 -0300 Subject: [PATCH 3/4] feat: insert activity from background payments --- .../main/java/to/bitkit/fcm/WakeNodeWorker.kt | 27 +++++++++---- .../to/bitkit/repositories/ActivityRepo.kt | 40 +++++++++++++++++++ .../java/to/bitkit/viewmodels/AppViewModel.kt | 19 +-------- 3 files changed, 60 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/to/bitkit/fcm/WakeNodeWorker.kt b/app/src/main/java/to/bitkit/fcm/WakeNodeWorker.kt index 8c371946b..8a281e6b7 100644 --- a/app/src/main/java/to/bitkit/fcm/WakeNodeWorker.kt +++ b/app/src/main/java/to/bitkit/fcm/WakeNodeWorker.kt @@ -25,6 +25,8 @@ import to.bitkit.models.BlocktankNotificationType.wakeToTimeout import to.bitkit.models.NewTransactionSheetDetails import to.bitkit.models.NewTransactionSheetDirection import to.bitkit.models.NewTransactionSheetType +import to.bitkit.repositories.ActivityRepo +import to.bitkit.repositories.BlocktankRepo import to.bitkit.repositories.LightningRepo import to.bitkit.services.CoreService import to.bitkit.ui.pushNotification @@ -38,6 +40,8 @@ class WakeNodeWorker @AssistedInject constructor( @Assisted private val workerParams: WorkerParameters, private val coreService: CoreService, private val lightningRepo: LightningRepo, + private val blocktankRepo: BlocktankRepo, + private val activityRepo: ActivityRepo, ) : CoroutineWorker(appContext, workerParams) { private val self = this @@ -143,15 +147,22 @@ class WakeNodeWorker @AssistedInject constructor( lightningRepo.getChannels()?.find { it.channelId == event.channelId }?.let { channel -> val sats = channel.amountOnClose self.bestAttemptContent?.title = "Received ⚡ $sats sats" - // Save for UI to pick up - NewTransactionSheetDetails.save( - appContext, - NewTransactionSheetDetails( - type = NewTransactionSheetType.LIGHTNING, - direction = NewTransactionSheetDirection.RECEIVED, - sats = channel.amountOnClose.toLong(), + + val cjitOrder = channel.let { blocktankRepo.getCjitOrder(it) } + if (cjitOrder != null) { + val amount = channel.amountOnClose.toLong() + + // Save for UI to pick up + NewTransactionSheetDetails.save( + appContext, + NewTransactionSheetDetails( + type = NewTransactionSheetType.LIGHTNING, + direction = NewTransactionSheetDirection.RECEIVED, + sats = amount, + ) ) - ) + activityRepo.insertActivityFromChannel(cjitOrder = cjitOrder, channel = channel) + } } } else if (self.notificationType == orderPaymentConfirmed) { self.bestAttemptContent?.title = "Channel opened" diff --git a/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt b/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt index 5928011c6..eea44e120 100644 --- a/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt +++ b/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt @@ -3,6 +3,9 @@ package to.bitkit.repositories import com.synonym.bitkitcore.Activity import com.synonym.bitkitcore.Activity.Onchain import com.synonym.bitkitcore.ActivityFilter +import com.synonym.bitkitcore.IcJitEntry +import com.synonym.bitkitcore.LightningActivity +import com.synonym.bitkitcore.PaymentState import com.synonym.bitkitcore.PaymentType import com.synonym.bitkitcore.SortDirection import kotlinx.coroutines.CoroutineDispatcher @@ -14,6 +17,7 @@ import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.withContext import kotlinx.coroutines.withTimeout +import org.lightningdevkit.ldknode.ChannelDetails import org.lightningdevkit.ldknode.PaymentDetails import to.bitkit.data.AppDb import to.bitkit.data.CacheStore @@ -22,6 +26,7 @@ import to.bitkit.data.dto.PendingBoostActivity import to.bitkit.data.dto.TransferType import to.bitkit.data.entities.TagMetadataEntity import to.bitkit.di.BgDispatcher +import to.bitkit.ext.amountOnClose import to.bitkit.ext.matchesPaymentId import to.bitkit.ext.nowTimestamp import to.bitkit.ext.rawId @@ -504,6 +509,41 @@ class ActivityRepo @Inject constructor( } } + /** + * Inserts a new activity + */ + suspend fun insertActivityFromChannel( + cjitOrder: IcJitEntry?, + channel: ChannelDetails, + ): Result = withContext(bgDispatcher) { + runCatching { + requireNotNull(cjitOrder) + + val amount = channel.amountOnClose + val now = nowTimestamp().toEpochMilli().toULong() + + return@withContext insertActivity( + Activity.Lightning( + LightningActivity( + id = channel.fundingTxo?.txid.orEmpty(), + txType = PaymentType.RECEIVED, + status = PaymentState.SUCCEEDED, + value = amount, + fee = 0U, + invoice = cjitOrder.invoice.request, + message = "", + timestamp = now, + preimage = null, + createdAt = now, + updatedAt = null, + ) + ) + ) + }.onFailure { e -> + Logger.error("insertActivity error", e, context = TAG) + } + } + suspend fun addActivityToPendingBoost(pendingBoostActivity: PendingBoostActivity) = withContext(bgDispatcher) { cacheStore.addActivityToPendingBoost(pendingBoostActivity) } diff --git a/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt b/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt index 1c50baeec..a4f64be1f 100644 --- a/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt +++ b/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt @@ -236,24 +236,7 @@ class AppViewModel @Inject constructor( ), event = event ) - val now = nowTimestamp().toEpochMilli().toULong() - activityRepo.insertActivity( - Activity.Lightning( - LightningActivity( - id = channel.fundingTxo?.txid.orEmpty(), - txType = PaymentType.RECEIVED, - status = PaymentState.SUCCEEDED, - value = amount.toULong(), - fee = 0U, - invoice = cjitOrder.invoice.request, - message = "", - timestamp = now, - preimage = null, - createdAt = now, - updatedAt = null, - ) - ) - ) + activityRepo.insertActivityFromChannel(cjitOrder = cjitOrder, channel = channel) } else { toast( type = Toast.ToastType.LIGHTNING, From 210e213f376696c37c507500b5973f5a9c2eb371 Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Tue, 7 Oct 2025 08:26:30 -0300 Subject: [PATCH 4/4] chore: remove imports --- app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt b/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt index a4f64be1f..06e5d79bb 100644 --- a/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt +++ b/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt @@ -11,17 +11,14 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import androidx.navigation.NavOptions import androidx.navigation.navOptions -import com.synonym.bitkitcore.Activity import com.synonym.bitkitcore.ActivityFilter import com.synonym.bitkitcore.FeeRates -import com.synonym.bitkitcore.LightningActivity import com.synonym.bitkitcore.LightningInvoice import com.synonym.bitkitcore.LnurlAuthData import com.synonym.bitkitcore.LnurlChannelData import com.synonym.bitkitcore.LnurlPayData import com.synonym.bitkitcore.LnurlWithdrawData import com.synonym.bitkitcore.OnChainInvoice -import com.synonym.bitkitcore.PaymentState import com.synonym.bitkitcore.PaymentType import com.synonym.bitkitcore.Scanner import com.synonym.bitkitcore.decode @@ -63,7 +60,6 @@ import to.bitkit.ext.maxSendableSat import to.bitkit.ext.maxWithdrawableSat import to.bitkit.ext.minSendableSat import to.bitkit.ext.minWithdrawableSat -import to.bitkit.ext.nowTimestamp import to.bitkit.ext.rawId import to.bitkit.ext.removeSpaces import to.bitkit.ext.setClipboardText