Skip to content

Commit 48df7a4

Browse files
committed
fix: harden paykit receiver state
1 parent af9751a commit 48df7a4

4 files changed

Lines changed: 34 additions & 9 deletions

File tree

app/src/main/java/to/bitkit/repositories/PrivatePaykitRepo.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,15 @@ class PrivatePaykitRepo @Inject constructor(
153153
}
154154
}
155155

156-
suspend fun refreshSavedContactEndpoints(publicKey: String): Result<Unit> =
156+
suspend fun refreshSavedContactEndpoints(
157+
publicKey: String,
158+
savedPublicKeys: Collection<String>,
159+
): Result<Unit> =
157160
withContext(serializedDispatcher) {
158161
runSuspendCatching {
159-
val keys = rememberSavedContacts(listOf(publicKey), replacing = false)
162+
val normalizedKey = normalizedPublicKey(publicKey) ?: return@runSuspendCatching
163+
rememberSavedContacts(savedPublicKeys + normalizedKey, replacing = false)
164+
val keys = listOf(normalizedKey)
160165
if (!canPublishPrivateEndpoints()) {
161166
prepareRelevantPrivateLinksIfAvailable(keys, "refresh")
162167
return@runSuspendCatching

app/src/main/java/to/bitkit/ui/screens/profile/EditProfileViewModel.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,9 +269,6 @@ class EditProfileViewModel @Inject constructor(
269269
}
270270
val cleanupResult = privatePaykitRepo.removePublishedEndpointsForCleanup(TAG)
271271
if (cleanupResult.isFailure) {
272-
val error = requireNotNull(cleanupResult.exceptionOrNull()) {
273-
"Private Paykit cleanup failed without an error"
274-
}
275272
_uiState.update {
276273
it.copy(
277274
isSaving = false,

app/src/main/java/to/bitkit/usecases/RefreshContactPaykitReceiversUseCase.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ class RefreshContactPaykitReceiversUseCase @Inject constructor(
2222
suspend operator fun invoke(publicKey: String): Result<Unit> = withContext(ioDispatcher) {
2323
runSuspendCatching {
2424
pubkyRepo.refreshContactReceiverPaths(publicKey).getOrThrow()
25-
privatePaykitRepo.refreshSavedContactEndpoints(publicKey).getOrThrow()
25+
val savedPublicKeys = (pubkyRepo.contacts.value.map { it.publicKey } + publicKey).distinct()
26+
privatePaykitRepo.refreshSavedContactEndpoints(publicKey, savedPublicKeys).getOrThrow()
2627
}.onFailure {
2728
Logger.warn(
2829
"Failed to refresh Paykit receivers for '${PubkyPublicKeyFormat.redacted(publicKey)}'",

app/src/test/java/to/bitkit/usecases/RefreshContactPaykitReceiversUseCaseTest.kt

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package to.bitkit.usecases
22

3+
import kotlinx.coroutines.flow.MutableStateFlow
4+
import org.junit.Before
35
import org.junit.Test
46
import org.mockito.kotlin.inOrder
57
import org.mockito.kotlin.mock
68
import org.mockito.kotlin.never
79
import org.mockito.kotlin.verify
810
import org.mockito.kotlin.whenever
11+
import to.bitkit.models.PubkyProfile
912
import to.bitkit.repositories.PrivatePaykitRepo
1013
import to.bitkit.repositories.PubkyRepo
1114
import to.bitkit.test.BaseUnitTest
@@ -16,24 +19,43 @@ class RefreshContactPaykitReceiversUseCaseTest : BaseUnitTest() {
1619
private val pubkyRepo = mock<PubkyRepo>()
1720
private val privatePaykitRepo = mock<PrivatePaykitRepo>()
1821
private val contactKeys = listOf("pubky-alice", "pubky-bob")
22+
private val contacts = MutableStateFlow(
23+
contactKeys.map { publicKey ->
24+
PubkyProfile(
25+
publicKey = publicKey,
26+
name = publicKey,
27+
bio = "",
28+
imageUrl = null,
29+
links = emptyList(),
30+
status = null,
31+
)
32+
},
33+
)
1934

2035
private val sut = RefreshContactPaykitReceiversUseCase(
2136
ioDispatcher = testDispatcher,
2237
pubkyRepo = pubkyRepo,
2338
privatePaykitRepo = privatePaykitRepo,
2439
)
2540

41+
@Before
42+
fun setUp() {
43+
whenever(pubkyRepo.contacts).thenReturn(contacts)
44+
}
45+
2646
@Test
2747
fun `refreshes receiver paths before publishing the contact`() = test {
2848
whenever { pubkyRepo.refreshContactReceiverPaths(contactKeys.last()) }.thenReturn(Result.success(Unit))
29-
whenever { privatePaykitRepo.refreshSavedContactEndpoints(contactKeys.last()) }.thenReturn(Result.success(Unit))
49+
whenever {
50+
privatePaykitRepo.refreshSavedContactEndpoints(contactKeys.last(), contactKeys)
51+
}.thenReturn(Result.success(Unit))
3052

3153
val result = sut(contactKeys.last())
3254

3355
assertTrue(result.isSuccess)
3456
inOrder(pubkyRepo, privatePaykitRepo).apply {
3557
verify(pubkyRepo).refreshContactReceiverPaths(contactKeys.last())
36-
verify(privatePaykitRepo).refreshSavedContactEndpoints(contactKeys.last())
58+
verify(privatePaykitRepo).refreshSavedContactEndpoints(contactKeys.last(), contactKeys)
3759
}
3860
}
3961

@@ -45,6 +67,6 @@ class RefreshContactPaykitReceiversUseCaseTest : BaseUnitTest() {
4567
val result = sut(contactKeys.last())
4668

4769
assertEquals(error, result.exceptionOrNull())
48-
verify(privatePaykitRepo, never()).refreshSavedContactEndpoints(contactKeys.last())
70+
verify(privatePaykitRepo, never()).refreshSavedContactEndpoints(contactKeys.last(), contactKeys)
4971
}
5072
}

0 commit comments

Comments
 (0)