Skip to content

Commit de2cee7

Browse files
committed
fix: tag pending contact payments
1 parent 7b030f1 commit de2cee7

2 files changed

Lines changed: 78 additions & 35 deletions

File tree

app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,7 @@ class AppViewModel @Inject constructor(
699699
event.paymentHash.let { paymentHash ->
700700
activityRepo.handlePaymentEvent(paymentHash)
701701
if (pendingPaymentRepo.isPending(paymentHash)) {
702+
syncContactForActivity(paymentHash)
702703
pendingPaymentRepo.resolve(PendingPaymentResolution.Success(paymentHash))
703704
if (_currentSheet.value !is Sheet.Send || !pendingPaymentRepo.isActive(paymentHash)) {
704705
notifyPendingPaymentSucceeded()

app/src/test/java/to/bitkit/viewmodels/AppViewModelSendFlowTest.kt

Lines changed: 77 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ import kotlinx.coroutines.flow.flowOf
99
import kotlinx.coroutines.test.advanceUntilIdle
1010
import org.junit.Before
1111
import org.junit.Test
12+
import org.lightningdevkit.ldknode.Event
1213
import org.mockito.kotlin.any
1314
import org.mockito.kotlin.anyOrNull
1415
import org.mockito.kotlin.mock
16+
import org.mockito.kotlin.verify
1517
import org.mockito.kotlin.whenever
1618
import to.bitkit.data.AppCacheData
1719
import to.bitkit.data.CacheStore
@@ -31,6 +33,7 @@ import to.bitkit.repositories.HealthRepo
3133
import to.bitkit.repositories.LightningRepo
3234
import to.bitkit.repositories.LightningState
3335
import to.bitkit.repositories.PendingPaymentRepo
36+
import to.bitkit.repositories.PendingPaymentResolution
3437
import to.bitkit.repositories.PreActivityMetadataRepo
3538
import to.bitkit.repositories.PubkyRepo
3639
import to.bitkit.repositories.PublicPaykitRepo
@@ -79,18 +82,25 @@ class AppViewModelSendFlowTest : BaseUnitTest() {
7982
private val formatMoneyValue = mock<FormatMoneyValue>()
8083

8184
private val balanceState = MutableStateFlow(BalanceState())
85+
private val nodeEvents = MutableSharedFlow<Event>()
8286

8387
private val timedSheetManager = mock<TimedSheetManager>()
8488

8589
@Before
8690
fun setUp() {
91+
stubRepositories()
92+
sut = createViewModel()
93+
}
94+
95+
private fun stubRepositories() {
8796
whenever(context.getString(any())).thenReturn("")
8897
whenever(connectivityRepo.isOnline).thenReturn(MutableStateFlow(ConnectivityState.CONNECTED))
8998
whenever(healthRepo.healthState).thenReturn(MutableStateFlow(mock()))
9099
whenever(lightningRepo.lightningState).thenReturn(MutableStateFlow(LightningState()))
91-
whenever(lightningRepo.nodeEvents).thenReturn(MutableSharedFlow())
100+
whenever(lightningRepo.nodeEvents).thenReturn(nodeEvents)
92101
whenever(walletRepo.balanceState).thenReturn(balanceState)
93102
whenever(walletRepo.walletState).thenReturn(MutableStateFlow(WalletState()))
103+
whenever(walletRepo.walletExists()).thenReturn(true)
94104
whenever(settingsStore.data).thenReturn(flowOf(SettingsData()))
95105
whenever(cacheStore.data).thenReturn(flowOf(AppCacheData()))
96106
whenever(transferRepo.activeTransfers).thenReturn(flowOf(emptyList()))
@@ -108,42 +118,42 @@ class AppViewModelSendFlowTest : BaseUnitTest() {
108118
whenever { lightningRepo.getFeeRateForSpeed(any(), anyOrNull()) }
109119
.thenReturn(Result.success(2u))
110120
whenever { lightningRepo.canSend(any(), any()) }.thenReturn(true)
111-
112-
sut = AppViewModel(
113-
connectivityRepo = connectivityRepo,
114-
healthRepo = healthRepo,
115-
toastManagerProvider = { mock<ToastQueueManager>() },
116-
timedSheetManagerProvider = { timedSheetManager },
117-
context = context,
118-
bgDispatcher = testDispatcher,
119-
keychain = keychain,
120-
lightningRepo = lightningRepo,
121-
pendingPaymentRepo = pendingPaymentRepo,
122-
walletRepo = walletRepo,
123-
backupRepo = backupRepo,
124-
settingsStore = settingsStore,
125-
currencyRepo = currencyRepo,
126-
activityRepo = activityRepo,
127-
preActivityMetadataRepo = preActivityMetadataRepo,
128-
blocktankRepo = blocktankRepo,
129-
appUpdaterService = appUpdaterService,
130-
notifyPaymentReceivedHandler = notifyPaymentReceivedHandler,
131-
cacheStore = cacheStore,
132-
transferRepo = transferRepo,
133-
migrationService = migrationService,
134-
coreService = coreService,
135-
publicPaykitRepo = publicPaykitRepo,
136-
appUpdateSheet = mock(),
137-
backupSheet = mock(),
138-
notificationsSheet = mock(),
139-
quickPaySheet = mock(),
140-
highBalanceSheet = mock(),
141-
formatMoneyValue = formatMoneyValue,
142-
widgetsRepo = widgetsRepo,
143-
pubkyRepo = pubkyRepo,
144-
)
145121
}
146122

123+
private fun createViewModel() = AppViewModel(
124+
connectivityRepo = connectivityRepo,
125+
healthRepo = healthRepo,
126+
toastManagerProvider = { mock<ToastQueueManager>() },
127+
timedSheetManagerProvider = { timedSheetManager },
128+
context = context,
129+
bgDispatcher = testDispatcher,
130+
keychain = keychain,
131+
lightningRepo = lightningRepo,
132+
pendingPaymentRepo = pendingPaymentRepo,
133+
walletRepo = walletRepo,
134+
backupRepo = backupRepo,
135+
settingsStore = settingsStore,
136+
currencyRepo = currencyRepo,
137+
activityRepo = activityRepo,
138+
preActivityMetadataRepo = preActivityMetadataRepo,
139+
blocktankRepo = blocktankRepo,
140+
appUpdaterService = appUpdaterService,
141+
notifyPaymentReceivedHandler = notifyPaymentReceivedHandler,
142+
cacheStore = cacheStore,
143+
transferRepo = transferRepo,
144+
migrationService = migrationService,
145+
coreService = coreService,
146+
publicPaykitRepo = publicPaykitRepo,
147+
appUpdateSheet = mock(),
148+
backupSheet = mock(),
149+
notificationsSheet = mock(),
150+
quickPaySheet = mock(),
151+
highBalanceSheet = mock(),
152+
formatMoneyValue = formatMoneyValue,
153+
widgetsRepo = widgetsRepo,
154+
pubkyRepo = pubkyRepo,
155+
)
156+
147157
@Test
148158
fun `canSwitchWallet is false when not unified`() = test {
149159
sut.setSendEvent(SendEvent.AmountChange(1000u))
@@ -254,6 +264,30 @@ class AppViewModelSendFlowTest : BaseUnitTest() {
254264
assertEquals(before, sut.sendUiState.value.payMethod)
255265
}
256266

267+
@Test
268+
fun `pending contact lightning success tags activity`() = test {
269+
val contactKey = "pubkycontact"
270+
val paymentHash = "pending_hash"
271+
whenever(pendingPaymentRepo.isPending(paymentHash)).thenReturn(true)
272+
whenever(pendingPaymentRepo.isActive(paymentHash)).thenReturn(false)
273+
whenever(activityRepo.setContact(contactKey, paymentHash)).thenReturn(Result.success(Unit))
274+
advanceUntilIdle()
275+
276+
setPendingContactPaymentContext(paymentHash, contactKey)
277+
nodeEvents.emit(
278+
Event.PaymentSuccessful(
279+
paymentId = "payment_id",
280+
paymentHash = paymentHash,
281+
paymentPreimage = "preimage",
282+
feePaidMsat = 10uL,
283+
),
284+
)
285+
advanceUntilIdle()
286+
287+
verify(pendingPaymentRepo).resolve(PendingPaymentResolution.Success(paymentHash))
288+
verify(activityRepo).setContact(contactPublicKey = contactKey, forPaymentId = paymentHash)
289+
}
290+
257291
@Test
258292
fun `amount change clears confirmedWarnings`() = test {
259293
setUnifiedState(amount = 1000u)
@@ -307,6 +341,14 @@ class AppViewModelSendFlowTest : BaseUnitTest() {
307341
assertEquals(0L, sut.sendUiState.value.lastLightningFee)
308342
}
309343

344+
@Suppress("UNCHECKED_CAST")
345+
private fun setPendingContactPaymentContext(paymentHash: String, publicKey: String) {
346+
val field = AppViewModel::class.java.getDeclaredField("pendingContactPaymentContexts")
347+
field.isAccessible = true
348+
val contexts = field.get(sut) as MutableMap<String, ContactPaymentContext>
349+
contexts[paymentHash] = ContactPaymentContext(publicKey)
350+
}
351+
310352
@Suppress("UNCHECKED_CAST")
311353
private fun setSendState(state: SendUiState) {
312354
val field = AppViewModel::class.java.getDeclaredField("_sendUiState")

0 commit comments

Comments
 (0)