Skip to content

Commit 17c7256

Browse files
committed
fix: propagate rbf contact updates
1 parent e240518 commit 17c7256

2 files changed

Lines changed: 68 additions & 0 deletions

File tree

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,11 +386,29 @@ class ActivityRepo @Inject constructor(
386386
val updatedAt = nowTimestamp().epochSecond.toULong()
387387
val updatedActivity = activity.withContact(normalizedKey, updatedAt)
388388
updateActivity(updatedActivity.rawId(), updatedActivity).getOrThrow()
389+
updateReplacementContactIfNeeded(updatedActivity, normalizedKey, updatedAt)
389390
}.onFailure {
390391
Logger.error("Failed to set contact for payment '$forPaymentId'", it, context = TAG)
391392
}
392393
}
393394

395+
private suspend fun updateReplacementContactIfNeeded(
396+
activity: Activity,
397+
normalizedKey: String,
398+
updatedAt: ULong,
399+
) {
400+
if (activity !is Activity.Onchain || activity.v1.doesExist || activity.v1.txType != PaymentType.SENT) return
401+
402+
getActivities(filter = ActivityFilter.ONCHAIN).getOrThrow()
403+
.filterIsInstance<Activity.Onchain>()
404+
.filter { activity.v1.txId in it.v1.boostTxIds }
405+
.filterNot { PubkyPublicKeyFormat.matches(it.v1.contact, normalizedKey) }
406+
.forEach {
407+
val updatedReplacement = Activity.Onchain(it.v1.copy(contact = normalizedKey, updatedAt = updatedAt))
408+
updateActivity(updatedReplacement.rawId(), updatedReplacement).getOrThrow()
409+
}
410+
}
411+
394412
private suspend fun findActivityForPaymentId(forPaymentId: String, syncLdkPayments: Boolean): Activity? {
395413
val activity = getActivityByPaymentId(forPaymentId)
396414
if (activity != null) return activity

app/src/test/java/to/bitkit/repositories/ActivityRepoTest.kt

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,56 @@ class ActivityRepoTest : BaseUnitTest() {
304304
assertEquals(listOf(replacementActivity), result.getOrThrow())
305305
}
306306

307+
@Test
308+
fun `setContact propagates contact to replacement transaction`() = test {
309+
val contactPublicKey = "pubky3rsduhcxpw74snwyct86m38c63j3pq8x4ycqikxg64roik8yw5xg"
310+
val replacedTxId = "replaced_tx_id"
311+
val replacedActivity = createOnchainActivity(
312+
id = "replaced_activity_id",
313+
txId = replacedTxId,
314+
doesExist = false,
315+
)
316+
val replacementActivity = createOnchainActivity(
317+
id = "replacement_activity_id",
318+
txId = "replacement_tx_id",
319+
boostTxIds = listOf(replacedTxId),
320+
)
321+
whenever(coreService.activity.getActivity(replacedTxId)).thenReturn(null)
322+
whenever(coreService.activity.getOnchainActivityByTxId(replacedTxId)).thenReturn(replacedActivity.v1)
323+
whenever(
324+
coreService.activity.get(
325+
filter = ActivityFilter.ONCHAIN,
326+
txType = null,
327+
tags = null,
328+
search = null,
329+
minDate = null,
330+
maxDate = null,
331+
limit = null,
332+
sortDirection = null,
333+
)
334+
).thenReturn(listOf(replacedActivity, replacementActivity))
335+
336+
val result = sut.setContact(
337+
contactPublicKey = contactPublicKey,
338+
forPaymentId = replacedTxId,
339+
syncLdkPayments = false,
340+
)
341+
342+
assertTrue(result.isSuccess)
343+
verify(coreService.activity).update(
344+
eq(replacedActivity.v1.id),
345+
argThat {
346+
this is Activity.Onchain && v1.contact == contactPublicKey
347+
},
348+
)
349+
verify(coreService.activity).update(
350+
eq(replacementActivity.v1.id),
351+
argThat {
352+
this is Activity.Onchain && v1.contact == contactPublicKey
353+
},
354+
)
355+
}
356+
307357
@Test
308358
fun `updateActivity updates successfully when not deleted`() = test {
309359
val activityId = "activity123"

0 commit comments

Comments
 (0)