Skip to content

fix: notify confirmed-only onchain receives - #1299

Open
jvsena42 wants to merge 6 commits into
masterfrom
fix/797-notify-confirmed-onchain-receive
Open

jvsena42 wants to merge 6 commits into
masterfrom
fix/797-notify-confirmed-onchain-receive

Conversation

@jvsena42

@jvsena42 jvsena42 commented Sep 17, 2026

Copy link
Copy Markdown
Member

Fixes #797
Related to #1275
E2E companion: synonymdev/bitkit-e2e-tests#231 (same branch name, so CI here runs against it)

This PR shows the received sheet and notification for onchain deposits that the wallet first sees already confirmed, without a prior mempool event.

Description

  • Routes confirmed onchain transaction events to the received-payment handler, in the foreground and in the background node service, so a deposit mined before any wallet sync saw it in the mempool is no longer silent.
  • Shows a confirmed-only receive only when its block timestamp is within one hour of the device clock, so confirmations replayed by a full scan after a restore stay silent.
  • Skips confirmed-only receives while a backup restore or migration is running.
  • Keeps a single sheet per deposit: a transaction already presented from its mempool event does not show again when it confirms, because the existing txid claim and persisted seen state still apply.
  • Skips the confirmed activity update when the activity already carries the confirmation, so the foreground path, which updates it before calling the handler, does not queue the same Core update twice.
  • Adds unit tests for the confirmed-only path, the dedupe with the mempool path, the background notification, and the restore, migration and age guards.

Out of Scope

  • NotifyPaymentReceivedHandler: a confirmed-only deposit found more than one hour after its block (for example, the app was killed while it confirmed and reopened later) stays silent, while a deposit still in the mempool at reopen always shows. A replay discriminator that does not depend on recency, such as a persisted flag set after the first post-restore full scan, is left for a follow-up.
  • AppViewModel: other receive side effects keyed to the mempool event, such as closing an open Receive sheet and the Paykit contact attachment and private address rotation, still run only on OnchainTransactionReceived. On device the Savings address did rotate after a confirmed-only receive.
  • RBF: if an already presented incoming tx is replaced and the replacement confirms before any mempool sync sees it, a second sheet can show when the replacement event has not been processed yet. The same race exists today for OnchainTransactionReceived.
  • LightningNodeService: after a process restart, a recent confirmation of a tx already seen through its mempool event still runs the handler's short retry delay (about 1.4 s) before skipping.
  • @boost_1 - Can do CPFP in the local e2e suite restores from seed and then mines, so the boosted receive becomes a confirmed-only receive and the sheet covers HeaderMenu. The sheet is correct there, so the spec dismisses it: test: dismiss confirmed-only receive sheet in boost_1 bitkit-e2e-tests#231.
  • NotifyPaymentReceivedHandler: the one-hour window is measured against the device clock, so a device whose clock is off by more than an hour never shows a confirmed-only receive, and ldk-node emits OnchainTransactionConfirmed once, so it cannot be recovered later. The mempool path is unaffected. A clock-independent reference, such as the timestamp of the tip block from the sync that produced the event, is left for the same follow-up as the replay discriminator above.
  • iOS parity: bitkit-ios#455 tracks the same bug; the follow-up should use the same one-hour block-timestamp rule instead of a block-depth rule, because the node's best block can lag behind the onchain wallet sync.

Design

Reuses the existing received sheet with no visual change: Payment received event

Preview

Figma Confirmed-only, foreground Confirmed-only, background
Figma payment received event Received sheet for confirmed-only deposit Payment Received notification for confirmed-only deposit

The wallet's primary display is USD, so fiat leads on device; the button label is chosen at random. Both are existing behaviour.

Deposit and mine in one command while on Home; the received sheet appears after the next sync:

confirmed-only-foreground.mp4

QA Notes

Manual Tests

  • 1. Regtest, app on Home → Receive → Savings address → deposit and mine 1 block in one command: received sheet shows once after the next sync and the log has no OnchainTransactionReceived for the txid.
  • 2a. regression: Home → deposit to a Savings address without mining: received sheet shows; dismiss it.
    • 2b. mine 1 block: no second sheet and no "Payment Received" notification.
  • 3a. Background payments on → app in background → deposit and mine 1 block in one command: exactly one "Payment Received" notification.
    • 3b. tap the notification: app opens on the received sheet; dismiss shows Home with no second sheet.
  • 4. regression: Restore a wallet with old onchain deposits: no received sheets or notifications for them.

The device run used the journeys/onchain-receive suite, committed in this PR at
journeys/onchain-receive/ (confirmed-only-received-sheet.xml,
mempool-then-confirmed-single-sheet.xml, confirmed-only-background-notification.xml, plus the
suite README.md and the journeys/README.md rows). The same diff inline:

journeys/onchain-receive
diff --git a/journeys/README.md b/journeys/README.md
index 403c5e230..63807b479 100644
--- a/journeys/README.md
+++ b/journeys/README.md
@@ -119,6 +119,7 @@ fixtures, push notifications) live in each suite's README.
 | [deeplinks](deeplinks) | 2 | `bitkit://screen/…` and sheet routing behind the dev-mode gate; no README |
 | [hardware-wallet](hardware-wallet) | 17 | Trezor over USB; needs the Trezor emulator |
 | [notification-permission](notification-permission) | 4 | Background-setup toggles |
+| [onchain-receive](onchain-receive) | 3 | Received sheet and notification for mempool-first and confirmed-only deposits |
 | [payment-requests](payment-requests) | 2 | Requires a linked fixture issuer; rejected shapes are unit fixtures |
 | [pubky-marketplace](pubky-marketplace) | 1 | Two-wallet Paykit marketplace payment; integration fixture required |
 | [widgets](widgets) | 2 | Needs no backend — the quickest way to see the loop work; no README |
@@ -141,6 +142,7 @@ Known differences in the corpus, as of the iOS port (synonymdev/bitkit-ios#691):
 | `hardware-wallet/usb-reconnect.xml` | `reconnect.xml` — over Bridge, since iOS cannot do WebUSB |
 | `hardware-wallet/receive-onchain.xml`, `hardware-wallet/send-onchain.xml` | not ported |
 | `payment-requests/requested-resolution-failure.xml` | not ported |
+| `onchain-receive/*` | not ported — bitkit-ios#455 tracks the same confirmed-only bug |
 | `deeplinks/*` | not ported — iOS registers the `bitkit` scheme but has no screen or sheet router |
 | — | `hardware-wallet/transfer-to-spending-over-max.xml` exists only on iOS |
 
diff --git a/journeys/onchain-receive/README.md b/journeys/onchain-receive/README.md
new file mode 100644
index 000000000..6aa704af7
--- /dev/null
+++ b/journeys/onchain-receive/README.md
@@ -0,0 +1,25 @@
+# Onchain receive journeys
+
+These journeys cover the received sheet and notification for onchain deposits (issue #797).
+
+ldk-node emits `OnchainTransactionReceived` when the wallet sync finds a transaction in the mempool
+and `OnchainTransactionConfirmed` when it confirms. A transaction that is mined before any sync sees
+it in the mempool produces only the confirmed event. Both events go through
+`NotifyPaymentReceivedHandler`, from `AppViewModel` in the foreground and `LightningNodeService` in
+the background.
+
+A confirmed-only receive is shown only when its block timestamp is within one hour of the device
+clock and no restore or migration is running. A full scan after a restore replays old confirmations
+and stays silent; that case cannot be driven on a funded device and is covered by
+`NotifyPaymentReceivedHandlerTest.kt`.
+
+## Preconditions
+
+- Onboarded regtest wallet with the node running. Fund and mine with the `lsp` helper at the repo root.
+- Wallet sync runs every 10s. For the confirmed-only journeys, run the deposit and the mine in one
+  shell command, then check the log: an `OnchainTransactionReceived` line for the txid means the
+  sync saw the mempool first and the run tested the other path.
+- The background journey needs background payments enabled (Settings > Notifications).
+- Every event the node emits is logged by `LightningService` as `LDK event fired: <json>` under the
+  `APP` logcat tag, so `adb logcat -d -s APP:V` is enough to tell the two paths apart.
+- The Receive sheet's tabs carry no test tag; select the Savings tab by its label.
diff --git a/journeys/onchain-receive/confirmed-only-background-notification.xml b/journeys/onchain-receive/confirmed-only-background-notification.xml
new file mode 100644
index 000000000..58bf496a1
--- /dev/null
+++ b/journeys/onchain-receive/confirmed-only-background-notification.xml
@@ -0,0 +1,22 @@
+<journey name="confirmed-only onchain receive in background posts one notification">
+  <description>
+    Covers issue #797 on the LightningNodeService path. With background payments enabled and the app
+    in the background, a deposit first seen already confirmed must post exactly one "Payment
+    Received" notification.
+
+    Precondition: onboarded regtest wallet with background payments enabled, so the "Bitkit is
+    running in background" foreground service notification is present.
+  </description>
+  <actions>
+    <action>Tap Receive (testTag "Receive") and verify the Receive sheet opens (testTag "ReceiveScreen")</action>
+    <action>Tap the "Savings" receive tab (the tab row carries no test tag), tap "Show Details" (testTag "ShowDetails") and read the address from testTag "ReceiveOnchainAddress"</action>
+    <action>Press back, then send the app to the background: adb shell input keyevent KEYCODE_HOME</action>
+    <action>Run in one command: ./lsp POST /regtest/chain/deposit '{"address":"&lt;savings addr&gt;","amountSat":7970}' &amp;&amp; ./lsp POST /regtest/chain/mine '{"count":1}'</action>
+    <action>Wait 40s</action>
+    <action>Run: adb shell dumpsys notification --noredact | grep -A3 "pkg=to.bitkit.dev"</action>
+    <action>Verify exactly one notification titled "Payment Received" is posted, with body "Received &lt;amount&gt;" carrying the fiat and BTC amounts in the order set by the primary display setting</action>
+    <action>Open the notification shade and tap the "Payment Received" notification</action>
+    <action>Verify the app opens with the received sheet (testTag "ReceivedTransaction") showing the deposited amount</action>
+    <action>Tap the sheet button (testTag "ReceivedTransactionButton") and verify the home screen shows with no second sheet</action>
+  </actions>
+</journey>
diff --git a/journeys/onchain-receive/confirmed-only-received-sheet.xml b/journeys/onchain-receive/confirmed-only-received-sheet.xml
new file mode 100644
index 000000000..7f4dbc286
--- /dev/null
+++ b/journeys/onchain-receive/confirmed-only-received-sheet.xml
@@ -0,0 +1,25 @@
+<journey name="confirmed-only onchain receive shows the received sheet">
+  <description>
+    Covers issue #797. An onchain deposit the wallet first sees already confirmed, with no prior
+    mempool event, must show the received sheet once. ldk-node emits OnchainTransactionConfirmed
+    without OnchainTransactionReceived in that case.
+
+    Precondition: onboarded regtest wallet, node running, app in the foreground on the home screen.
+    The deposit and the mine must run in one shell command so the 10s wallet sync does not see the
+    transaction in the mempool first. If the log shows OnchainTransactionReceived for the txid, the
+    run tested the mempool path instead; repeat with a new address.
+  </description>
+  <actions>
+    <action>Tap Receive (testTag "Receive") and verify the Receive sheet opens (testTag "ReceiveScreen")</action>
+    <action>Tap the "Savings" receive tab (the tab row carries no test tag), tap "Show Details" (testTag "ShowDetails") and read the address from testTag "ReceiveOnchainAddress"</action>
+    <action>Press back to return to the home screen</action>
+    <action>Run: adb logcat -c</action>
+    <action>Run in one command: ./lsp POST /regtest/chain/deposit '{"address":"&lt;savings addr&gt;","amountSat":21797}' &amp;&amp; ./lsp POST /regtest/chain/mine '{"count":1}'</action>
+    <action>Wait up to 30s for the next wallet sync</action>
+    <action>Run: adb logcat -d -s APP:V | grep &lt;txid&gt;</action>
+    <action>Verify the log shows an "LDK event fired" line with OnchainTransactionConfirmed for the txid and no OnchainTransactionReceived for it</action>
+    <action>Verify the received sheet (testTag "ReceivedTransaction") is visible with the deposited amount (testTag "MoneyText")</action>
+    <action>Tap the sheet button (testTag "ReceivedTransactionButton")</action>
+    <action>Wait 10s and verify the received sheet does not appear again</action>
+  </actions>
+</journey>
diff --git a/journeys/onchain-receive/mempool-then-confirmed-single-sheet.xml b/journeys/onchain-receive/mempool-then-confirmed-single-sheet.xml
new file mode 100644
index 000000000..6f912d135
--- /dev/null
+++ b/journeys/onchain-receive/mempool-then-confirmed-single-sheet.xml
@@ -0,0 +1,21 @@
+<journey name="mempool-first onchain receive shows one sheet after confirmation">
+  <description>
+    Covers issue #797. Confirmed events now reach the received-payment handler, so a deposit seen
+    in the mempool first must not show a second sheet when it confirms. The handler dedupes on the
+    txid and on the persisted seen state.
+
+    Precondition: onboarded regtest wallet, node running, app in the foreground on the home screen.
+  </description>
+  <actions>
+    <action>Tap Receive (testTag "Receive") and verify the Receive sheet opens (testTag "ReceiveScreen")</action>
+    <action>Tap the "Savings" receive tab (the tab row carries no test tag), tap "Show Details" (testTag "ShowDetails") and read the address from testTag "ReceiveOnchainAddress"</action>
+    <action>Press back to return to the home screen</action>
+    <action>Run: ./lsp POST /regtest/chain/deposit '{"address":"&lt;savings addr&gt;","amountSat":14797}'</action>
+    <action>Wait up to 30s and verify the received sheet (testTag "ReceivedTransaction") is visible with the deposited amount</action>
+    <action>Tap the sheet button (testTag "ReceivedTransactionButton")</action>
+    <action>Run: ./lsp POST /regtest/chain/mine '{"count":1}'</action>
+    <action>Run: adb logcat -d -s APP:V | grep &lt;txid&gt; and wait until an "LDK event fired" line shows OnchainTransactionConfirmed</action>
+    <action>Wait 30s after that event and verify the received sheet does not appear again</action>
+    <action>Verify no "Payment Received" notification is posted: adb shell dumpsys notification --noredact | grep "Payment Received"</action>
+  </actions>
+</journey>

Automated Checks

  • Unit tests added: NotifyPaymentReceivedHandlerTest.kt covers a recent confirmed-only receive showing the sheet and the notification, timestamps inside and outside the one-hour window in both directions, received-then-confirmed showing once, negative amounts, the restore and migration skips, and the confirmed activity update being applied once and skipped when it is already stored.
  • Unit tests modified: NotifyPaymentReceivedHandlerTest.kt moves the existing onchain cases to the new handler dependencies.
  • Unit tests added: LightningNodeServiceTest.kt covers a background confirmed event reaching the handler and posting exactly one notification, and a handler skip posting none.
  • Unit tests added: AppViewModelSendFlowTest.kt covers the confirmed event updating the activity and then showing the sheet, and no handler call during a migration.
  • Local verification: just compile, just test, just lint.
  • CI: standard compile, unit test, and detekt checks run by the PR bot.

jvsena42 and others added 2 commits September 17, 2026 06:22
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jvsena42 jvsena42 self-assigned this Sep 17, 2026
@greptile-apps

greptile-apps Bot commented Sep 17, 2026

Copy link
Copy Markdown

RetriggerConfidence Score: 4/5

The PR appears safe to merge after addressing the non-blocking redundant activity processing for foreground confirmations.

Findings

  1. P2 Duplicate confirmed activity updates

Summary

This PR routes confirmed on-chain transactions through the existing received-payment presentation flow and suppresses restored, migrated, old, outgoing, and previously presented transactions.

  • Adds confirmed-event mapping and foreground/background routing.
  • Uses block-time recency plus restore and migration state to identify eligible confirmed-only receives.
  • Extends unit coverage for presentation, notification, deduplication, and suppression behavior.
  • One activity-update ownership issue remains: eligible foreground confirmations can enqueue the same update multiple times.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    E[OnchainTransactionConfirmed] --> VM[AppViewModel]
    E --> S[LightningNodeService]
    VM --> U1[Update confirmed activity]
    VM --> H[NotifyPaymentReceivedHandler]
    S --> H
    H --> G{Recent and not restoring or migrating?}
    G -->|No| X[Skip presentation]
    G -->|Yes| U2[Update confirmed activity again]
    U2 --> D{Transaction eligible and unclaimed?}
    D -->|No| X
    D -->|Yes, app visible| Sheet[Show received sheet]
    D -->|Yes, app backgrounded| Notification[Post notification and cache sheet]
Loading

Reviews (1) · Last reviewed commit: "fix: gate confirmed-only receives on blo..."

Comment thread app/src/main/java/to/bitkit/domain/commands/NotifyPaymentReceivedHandler.kt Outdated
@github-actions

github-actions Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Regtest APK

Built from c67782e (run).

Download bitkit-dev-debug universal APK (expires in 30 days).

@jvsena42

Copy link
Copy Markdown
Member Author

CI: @boost_1 - Can do CPFP fails on this branch

e2e-tests-local - onchain_boost_receive_widgets fails here across three runs, and the last run had a healthy regtest stack, so it is not the infra flake the first two runs hit (electrs failed / bitcoind RPC polling failed).

Only one spec fails; the other 8 in the shard pass:

» test/specs/boost.e2e.ts
   ✖ @boost_1 - Can do CPFP
   ✓ @boost_2 - Can do RBF
Error: element ("...resourceId("HeaderMenu")") still not displayed after 30000ms
    at async doNavigationClose (test/helpers/navigation.ts:76:3)
    at async <anonymous> (test/specs/boost.e2e.ts:123:5)

The step order in that test is: receive unconfirmed → CPFP boost → restore the wallet from seed → reinstall → mine 1 block → doNavigationClose.

The reinstalled wallet never saw the boosted transaction in the mempool, so the mined block makes it a confirmed-only receive. That is exactly the path this PR adds: Event.OnchainTransactionConfirmed now reaches NotifyPaymentReceivedHandler, and neither guard stops it — the restore has finished, so backupRepo.isRestoring is false, and the block was mined seconds earlier, so it is well inside MAX_CONFIRMED_ONLY_AGE. The received sheet opens over Home and HeaderMenu is not tappable.

The same shard, including @boost_1, passes on #1171 in the same time window, so the test is not broken on master.

The sheet is arguably correct here — the wallet really did receive a confirmed transaction it had not seen before — in which case the fix belongs in bitkit-e2e-tests (dismiss the sheet after the restore-and-mine step), the way #809 shipped synonymdev/bitkit-e2e-tests#225. The alternative is to widen the guard so a confirmation that lands shortly after a restore stays silent. Leaving the call to the reviewer rather than guessing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jvsena42

Copy link
Copy Markdown
Member Author

Settled the @boost_1 - Can do CPFP failure on the e2e side: synonymdev/bitkit-e2e-tests#230.

Checked the spec against the branch. The step order is receive unconfirmed, CPFP boost, restore from seed, reinstall, mineBlocks(1), doNavigationClose(). The restored wallet never saw the boosted tx in the mempool, the restore has finished by then so backupRepo.isRestoring is false, and the block is seconds old so it is inside MAX_CONFIRMED_ONLY_AGE. The sheet is the intended behaviour - it really is a receive the wallet had not seen - so the guard stays as it is and the spec dismisses the sheet between the mine and doNavigationClose().

The e2e PR adds dismissReceivedPaymentIfShown(), a tolerant wrapper around acknowledgeReceivedPayment() that does not throw when no sheet appears, because the same spec has to pass on iOS and on Android master where no sheet shows. acknowledgeReceivedPaymentIfPresent() could not be reused: it is strict on the local backend this shard runs on.

@boost_2 - Can do RBF also restores and mines and is left alone: that block confirms the outgoing RBF tx, and the incoming 100k was already confirmed before the restore, which matches it passing here today.

@jvsena42

Copy link
Copy Markdown
Member Author

Correction on the e2e link: the companion PR is now synonymdev/bitkit-e2e-tests#231. Same commit, on a branch named fix/797-notify-confirmed-onchain-receive so determine-e2e-branch resolves to it and this PR's e2e-tests-local shards run against the fixed spec. #230 is closed.

@jvsena42

Copy link
Copy Markdown
Member Author

CI is green on 24ab459. The rerun resolved the e2e branch to fix/797-notify-confirmed-onchain-receive (synonymdev/bitkit-e2e-tests#231) and e2e-tests-local - onchain_boost_receive_widgets passed in 23m, along with the other six local shards, build, lint and detekt.

Merge order: #231 first (or together), otherwise this PR is green only while the matching e2e branch exists.

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved — no HIGH/MEDIUM findings at head 24ab459b9. (Posted as a comment because GitHub does not allow approving your own PR.)

Inline: LOW — Device clock off by more than an hour keeps every confirmed-only receive silent

Checked: Traced both entry paths at the PR head: LightningRepo invokes the service handler sequentially and only then emits to AppViewModel, so in the background the service claims first and posts one notification while AppViewModel's later call hits isPresentationClaimed and skips; in the foreground the service's canPresent (App.currentActivity == null) fails and AppViewModel claims, so one sheet. Dedupe across process death does not depend on the in-memory presentationClaims set: markOnchainActivityAsSeen writes seenAt into the Core activity DB via present -> recordPresentation, and CoreService.shouldShowReceivedSheet returns false on seenAt != null, so a mempool-presented tx that confirms after a restart (foreground or background path) resolves to Skip; ldk-node calls eventHandled before onEvent so events are not replayed either. Sends, CPFP children and channel-funding/order payments carry a negative net amount_sats (ldk-node get_tx_details = received - sent) and exit on amountSats <= 0 before any activity write; coop-close and sweep transactions run the same findClosedChannelForTransaction / isTransfer / channelId checks as the existing mempool path, with lightningService.balances read live from node.listBalances(). ldk-node rc.66 updates the payment store before returning wallet events, so handleOnchainTransactionConfirmed finds the payment and creates the activity before shouldShowReceivedSheet runs. Restore, migration and the one-hour block-timestamp guard are evaluated before any state is written, and the greptile thread on the duplicate confirmed update is resolved by applyConfirmationIfMissing. iOS twin synonymdev/bitkit-ios#588 is open.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jvsena42
jvsena42 requested a review from ovitrif September 18, 2026 13:26

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved — no HIGH/MEDIUM findings at head 2a6b9dd68. (Posted as a comment because GitHub does not allow approving your own PR.)

Inline: LOW — grep -A3 "pkg=to.bitkit.dev" never prints the notification title the next step verifies; LOW — Cross-platform row says not ported, but the iOS twin fixes the same behaviour without the journeys

Checked: Round 3 (2a6b9dd, new journeys): Round 3 delta is journeys only (three onchain-receive journeys, the suite README and two rows in journeys/README.md). Every testTag the journeys name exists at head: Receive (TabBar.kt:156), ReceiveScreen (ReceiveSheet.kt:144), ShowDetails and ReceiveOnchainAddress (ReceiveQrScreen.kt:427/658), ReceivedTransaction and ReceivedTransactionButton (NewTransactionSheet.kt:161/194), MoneyText (Money.kt). The preconditions are reachable with repo tooling: ./lsp at the root wraps the blocktank-api script, deposit returns the txid the log grep needs, Env.walletSyncIntervalSecs is 10, and LightningService logs every event as LDK event fired: <json> at debug level under the APP tag with the event class name as type. The staging regtest tip timestamp was checked against the wall clock (about 5 minutes apart), so the one-hour MAX_CONFIRMED_ONLY_AGE guard does not make the confirmed-only journeys false-fail today. The background flow matches the code: App.currentActivity clears on stop, LightningNodeService claims and posts Payment Received / Received %s and caches the sheet, AppViewModel's later call skips on the claim, and ContentView ON_START calls consumePaymentReceivedInBackground, so tapping the auto-cancel notification opens the received sheet once. The mempool-then-confirmed journey would catch a second sheet if the txid claim or seenAt dedupe regressed.

Comment thread journeys/onchain-receive/confirmed-only-background-notification.xml Outdated
Comment thread journeys/README.md Outdated
jvsena42 and others added 2 commits September 18, 2026 11:06
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved — no blocking HIGH/MEDIUM findings at head c67782eb6. (Posted as a comment because GitHub does not allow approving your own PR.)

Checked: Round 4 (e2be5d9, c67782e): both journey LOWs are fixed. Round 4 covers two journey-only commits that answer my earlier LOWs. e2be5d9: the new grep matches what AOSP NotificationRecord prints inside the extras block under --noredact (android.title=String (Payment Received), android.text=String (Received ...)). The receive notification is posted through Context.pushNotification (Notifications.kt:84-86) with plain Strings from ReceivedNotificationContent.build (R.string.notification__received__title = "Payment Received", notification__received__body_amount = "Received %s"), so the extras class is String and both patterns hit. The foreground-service notification uses app_name ("Bitkit Regtest" on dev, build.gradle.kts:205) and notification__service__body, so it matches neither pattern and the title count is exact. c67782e: the cross-platform row now says the port is pending in synonymdev/bitkit-ios#588 and records both adaptations (restore-flag replay guard instead of the one-hour window, no foreground-service counterpart for the background notification journey), which is what I asked for. No new findings.

@ovi-reviewer ovi-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: ✅ Approve


Review: diff 13 files.

Findings:
N/A

Audit:
Audited - no findings.

Coverage:
QA: journeys and manual tests await green CI checks


Reviewed by claude-opus-5-xhigh via gh-pr-review-loop skill
Commands: @ovi-reviewer review · test · retest · audit (author or owner)

@ovitrif

ovitrif commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator

@jvsena42 ci failed

@jvsena42

Copy link
Copy Markdown
Member Author

Looked at it: infra, not the change. The settings shard failed in its before all hook waiting for TotalBalance-primary for 60 s, and the same job log has Failed to load snapshot 'default_boot', three adb ... failed with exit code 1 lines and Failed to find ColorBuffer: 209 — the app never reached Home on that runner. Every other shard passed, including onchain_boost_receive_widgets, which is the one this PR actually affects.

That shard has failed the same way on several PRs in this batch this afternoon. Re-running the failed jobs now. The real e2e issue this PR did cause is already handled separately in synonymdev/bitkit-e2e-tests#231, which dismisses the received sheet in @boost_1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

android: no received transaction notification when tx confirms without being seen in mempool

2 participants