11package to.bitkit.viewmodels
22
33import android.content.Context
4+ import com.synonym.bitkitcore.LightningInvoice
5+ import com.synonym.bitkitcore.NetworkType
6+ import com.synonym.bitkitcore.Scanner
47import kotlinx.collections.immutable.persistentListOf
58import kotlinx.coroutines.ExperimentalCoroutinesApi
69import kotlinx.coroutines.flow.MutableSharedFlow
@@ -27,6 +30,7 @@ import to.bitkit.models.TransactionSpeed
2730import to.bitkit.repositories.ActivityRepo
2831import to.bitkit.repositories.BackupRepo
2932import to.bitkit.repositories.BlocktankRepo
33+ import to.bitkit.repositories.BlocktankState
3034import to.bitkit.repositories.ConnectivityRepo
3135import to.bitkit.repositories.ConnectivityState
3236import to.bitkit.repositories.CurrencyRepo
@@ -46,7 +50,9 @@ import to.bitkit.services.AppUpdaterService
4650import to.bitkit.services.CoreService
4751import to.bitkit.services.MigrationService
4852import to.bitkit.test.BaseUnitTest
53+ import to.bitkit.ui.components.Sheet
4954import to.bitkit.ui.shared.toast.ToastQueueManager
55+ import to.bitkit.ui.sheets.SendRoute
5056import to.bitkit.usecases.FormatMoneyValue
5157import to.bitkit.utils.timedsheets.TimedSheetManager
5258import kotlin.test.assertEquals
@@ -108,6 +114,8 @@ class AppViewModelSendFlowTest : BaseUnitTest() {
108114 whenever(settingsStore.data).thenReturn(settingsData)
109115 whenever(cacheStore.data).thenReturn(flowOf(AppCacheData ()))
110116 whenever(transferRepo.activeTransfers).thenReturn(flowOf(emptyList()))
117+ whenever(blocktankRepo.blocktankState).thenReturn(MutableStateFlow (BlocktankState ()))
118+ whenever { blocktankRepo.refreshInfo() }.thenReturn(Result .success(Unit ))
111119 whenever(timedSheetManager.currentSheet).thenReturn(MutableStateFlow (null ))
112120 whenever(migrationService.isShowingMigrationLoading).thenReturn(MutableStateFlow (false ))
113121 whenever { migrationService.needsPostMigrationSync() }.thenReturn(false )
@@ -313,6 +321,32 @@ class AppViewModelSendFlowTest : BaseUnitTest() {
313321 assertNull(pendingContactPaymentContext(paymentHash))
314322 }
315323
324+ @Test
325+ fun `lightning scan uses QuickPay when enabled` () = test {
326+ val bolt11 = " lnbcrt1quickpay"
327+ enableQuickPay(thresholdSats = 1000u )
328+ stubLightningScan(bolt11 = bolt11, amountSats = 500u )
329+
330+ sut.onScanResult(bolt11)
331+ advanceUntilIdle()
332+
333+ assertEquals(QuickPayData .Bolt11 (sats = 500u , bolt11 = bolt11), sut.quickPayData.value)
334+ assertEquals(Sheet .Send (SendRoute .QuickPay ), sut.currentSheet.value)
335+ }
336+
337+ @Test
338+ fun `contact lightning payment skips QuickPay and opens confirm` () = test {
339+ val bolt11 = " lnbcrt1contact"
340+ enableQuickPay(thresholdSats = 1000u )
341+ stubLightningScan(bolt11 = bolt11, amountSats = 500u )
342+
343+ sut.openContactPayment(paymentRequest = bolt11, publicKey = " pubkycontact" )
344+ advanceUntilIdle()
345+
346+ assertNull(sut.quickPayData.value)
347+ assertEquals(Sheet .Send (SendRoute .Confirm ), sut.currentSheet.value)
348+ }
349+
316350 @Test
317351 fun `channel ready refreshes public Paykit endpoints when sharing enabled` () = test {
318352 enablePublicPaykitSharing()
@@ -404,6 +438,28 @@ class AppViewModelSendFlowTest : BaseUnitTest() {
404438 assertEquals(0L , sut.sendUiState.value.lastLightningFee)
405439 }
406440
441+ private fun enableQuickPay (thresholdSats : ULong ) {
442+ settingsData.value = SettingsData (isQuickPayEnabled = true , quickPayAmount = 5 )
443+ whenever(currencyRepo.convertFiatToSats(5.0 , " USD" )).thenReturn(Result .success(thresholdSats))
444+ }
445+
446+ private suspend fun stubLightningScan (bolt11 : String , amountSats : ULong ) {
447+ whenever(coreService.decode(bolt11)).thenReturn(Scanner .Lightning (lightningInvoice(bolt11, amountSats)))
448+ whenever(lightningRepo.canSend(amountSats)).thenReturn(true )
449+ }
450+
451+ private fun lightningInvoice (bolt11 : String , amountSats : ULong ) = LightningInvoice (
452+ bolt11 = bolt11,
453+ paymentHash = byteArrayOf(1 , 2 , 3 ),
454+ amountSatoshis = amountSats,
455+ timestampSeconds = 0u ,
456+ expirySeconds = 86_400u ,
457+ isExpired = false ,
458+ description = " " ,
459+ networkType = NetworkType .REGTEST ,
460+ payeeNodeId = null ,
461+ )
462+
407463 private suspend fun enablePublicPaykitSharing () {
408464 settingsData.value = SettingsData (sharesPublicPaykitEndpoints = true )
409465 walletState.value = WalletState (onchainAddress = " bc1qtest" )
0 commit comments