@@ -11,6 +11,7 @@ import androidx.lifecycle.ViewModel
1111import androidx.lifecycle.viewModelScope
1212import androidx.navigation.NavOptions
1313import androidx.navigation.navOptions
14+ import com.synonym.bitkitcore.Activity
1415import com.synonym.bitkitcore.ActivityFilter
1516import com.synonym.bitkitcore.FeeRates
1617import com.synonym.bitkitcore.LightningInvoice
@@ -234,56 +235,22 @@ class AppViewModel @Inject constructor(
234235 NotifyPaymentReceived .Command .from(event)?.let { handlePaymentReceived(it, event) }
235236 }
236237
237- is Event .ChannelReady -> {
238- val channel = lightningRepo.getChannels()?.find { it.channelId == event.channelId }
239- val cjitEntry = channel?.let { blocktankRepo.getCjitEntry(it) }
240- if (cjitEntry != null ) {
241- val amount = channel.amountOnClose.toLong()
242- showNewTransactionSheet(
243- NewTransactionSheetDetails (
244- type = NewTransactionSheetType .LIGHTNING ,
245- direction = NewTransactionSheetDirection .RECEIVED ,
246- sats = amount,
247- ),
248- event,
249- )
250- activityRepo.insertActivityFromCjit(cjitEntry = cjitEntry, channel = channel)
251- } else {
252- toast(
253- type = Toast .ToastType .LIGHTNING ,
254- title = context.getString(R .string.lightning__channel_opened_title),
255- description = context.getString(R .string.lightning__channel_opened_msg),
256- )
257- }
258- }
238+ is Event .ChannelReady -> notifyChannelReady(event)
259239
260240 is Event .ChannelPending -> Unit
261241 is Event .ChannelClosed -> Unit
262242
263- is Event .PaymentSuccessful -> {
264- val paymentHash = event.paymentHash
265- // TODO Temporary solution while LDK node doesn't return the sent value in the event
266- activityRepo.findActivityByPaymentId(
267- paymentHashOrTxId = paymentHash,
268- type = ActivityFilter .LIGHTNING ,
269- txType = PaymentType .SENT ,
270- retry = true
271- ).onSuccess { activity ->
272- handlePaymentSuccess(
273- NewTransactionSheetDetails (
274- type = NewTransactionSheetType .LIGHTNING ,
275- direction = NewTransactionSheetDirection .SENT ,
276- paymentHashOrTxId = event.paymentHash,
277- sats = activity.totalValue().toLong(),
278- ),
279- )
280- }.onFailure { e ->
281- Logger .warn(" Failed displaying sheet for event: $event " , e)
282- }
283- }
243+ is Event .PaymentSuccessful -> notifyPaymentSentOnLightning(event)
284244
285245 is Event .PaymentClaimable -> Unit
286- is Event .PaymentFailed -> Unit
246+ is Event .PaymentFailed -> {
247+ toast(
248+ type = Toast .ToastType .ERROR ,
249+ title = context.getString(R .string.wallet__toast_payment_failed_title),
250+ description = context.getString(R .string.wallet__toast_payment_failed_description),
251+ testTag = " PaymentFailedToast" ,
252+ )
253+ }
287254 is Event .PaymentForwarded -> Unit
288255
289256 is Event .OnchainTransactionReceived -> {
@@ -295,9 +262,47 @@ class AppViewModel @Inject constructor(
295262 is Event .SyncCompleted -> Unit
296263 is Event .BalanceChanged -> Unit
297264
298- is Event .OnchainTransactionEvicted -> Unit
299- is Event .OnchainTransactionReorged -> Unit
300- is Event .OnchainTransactionReplaced -> Unit
265+ is Event .OnchainTransactionEvicted -> {
266+ viewModelScope.launch(bgDispatcher) {
267+ if (! activityRepo.wasTransactionReplaced(event.txid)) {
268+ toast(
269+ type = Toast .ToastType .WARNING ,
270+ title = context.getString(R .string.wallet__toast_transaction_removed_title),
271+ description = context.getString(R .string.wallet__toast_transaction_removed_description),
272+ testTag = " TransactionRemovedToast" ,
273+ )
274+ }
275+ }
276+ }
277+
278+ is Event .OnchainTransactionReorged -> {
279+ toast(
280+ type = Toast .ToastType .WARNING ,
281+ title = context.getString(R .string.wallet__toast_transaction_unconfirmed_title),
282+ description = context.getString(R .string.wallet__toast_transaction_unconfirmed_description),
283+ testTag = " TransactionUnconfirmedToast" ,
284+ )
285+ }
286+
287+ is Event .OnchainTransactionReplaced -> {
288+ viewModelScope.launch(bgDispatcher) {
289+ if (activityRepo.isReceivedTransaction(event.txid)) {
290+ toast(
291+ type = Toast .ToastType .INFO ,
292+ title = context.getString(R .string.wallet__toast_received_transaction_replaced_title),
293+ description = context.getString(R .string.wallet__toast_received_transaction_replaced_description),
294+ testTag = " ReceivedTransactionReplacedToast" ,
295+ )
296+ } else {
297+ toast(
298+ type = Toast .ToastType .INFO ,
299+ title = context.getString(R .string.wallet__toast_transaction_replaced_title),
300+ description = context.getString(R .string.wallet__toast_transaction_replaced_description),
301+ testTag = " TransactionReplacedToast" ,
302+ )
303+ }
304+ }
305+ }
301306 }
302307 }.onFailure { e ->
303308 Logger .error(" LDK event handler error" , e, context = TAG )
@@ -306,6 +311,51 @@ class AppViewModel @Inject constructor(
306311 }
307312 }
308313
314+ private suspend fun notifyPaymentSentOnLightning (event : Event .PaymentSuccessful ): Result <Activity > {
315+ val paymentHash = event.paymentHash
316+ // TODO Temporary solution while LDK node doesn't return the sent value in the event
317+ return activityRepo.findActivityByPaymentId(
318+ paymentHashOrTxId = paymentHash,
319+ type = ActivityFilter .LIGHTNING ,
320+ txType = PaymentType .SENT ,
321+ retry = true
322+ ).onSuccess { activity ->
323+ handlePaymentSuccess(
324+ NewTransactionSheetDetails (
325+ type = NewTransactionSheetType .LIGHTNING ,
326+ direction = NewTransactionSheetDirection .SENT ,
327+ paymentHashOrTxId = event.paymentHash,
328+ sats = activity.totalValue().toLong(),
329+ ),
330+ )
331+ }.onFailure { e ->
332+ Logger .warn(" Failed displaying sheet for event: $event " , e)
333+ }
334+ }
335+
336+ private suspend fun notifyChannelReady (event : Event .ChannelReady ): Any {
337+ val channel = lightningRepo.getChannels()?.find { it.channelId == event.channelId }
338+ val cjitEntry = channel?.let { blocktankRepo.getCjitEntry(it) }
339+ return if (cjitEntry != null ) {
340+ val amount = channel.amountOnClose.toLong()
341+ showNewTransactionSheet(
342+ NewTransactionSheetDetails (
343+ type = NewTransactionSheetType .LIGHTNING ,
344+ direction = NewTransactionSheetDirection .RECEIVED ,
345+ sats = amount,
346+ ),
347+ event,
348+ )
349+ activityRepo.insertActivityFromCjit(cjitEntry = cjitEntry, channel = channel)
350+ } else {
351+ toast(
352+ type = Toast .ToastType .LIGHTNING ,
353+ title = context.getString(R .string.lightning__channel_opened_title),
354+ description = context.getString(R .string.lightning__channel_opened_msg),
355+ )
356+ }
357+ }
358+
309359 private fun handlePaymentReceived (
310360 receivedEvent : NotifyPaymentReceived .Command ,
311361 originalEvent : Event ,
@@ -1441,13 +1491,15 @@ class AppViewModel @Inject constructor(
14411491 description : String? = null,
14421492 autoHide : Boolean = true,
14431493 visibilityTime : Long = Toast .VISIBILITY_TIME_DEFAULT ,
1494+ testTag : String? = null,
14441495 ) {
14451496 currentToast = Toast (
14461497 type = type,
14471498 title = title,
14481499 description = description,
14491500 autoHide = autoHide,
1450- visibilityTime = visibilityTime
1501+ visibilityTime = visibilityTime,
1502+ testTag = testTag,
14511503 )
14521504 if (autoHide) {
14531505 viewModelScope.launch {
0 commit comments