Repository navigation
fix: open review for requests with an amount - #1763
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
[Medium impact] The latest changes appear safe to merge and address both earlier USDT findings. SummaryAmount-bearing Bitcoin and USDT requests open review directly and keep the requested amount fixed.
Reviews (7) · Last reviewed commit: "fix: space the usdt review error above t..." · Reviewed by Greptile |
|
Added to the 3.2.0 milestone: this fix was opened after the 3.1.0 cut and closes no issue, so this PR carries the milestone itself. |
talosmachina
left a comment
There was a problem hiding this comment.
No findings. On-chain BIP21 with a payable amount now opens Confirm (Back swaps it for Amount), and a USDT payment link with an amount quotes once on entry. Reviewed 5e95204, full tier, static: the branch was not built or run for this review, so the evidence is the code and CI.
What I checked, and 7 candidates I ruled out
Read in full: the diff; onScanOnchain, onAmountContinue, prepareCoinSelection, prepareHardwareSendFee, validateAmount, refreshOnchainSendIfNeeded, navigateToSendRoute, resetSendState in AppViewModel.kt; the Confirm and Amount routes and navigateToSendAmount in SendSheet.kt; UsdtWalletScreen.kt, UsdtViewModel.quote, UsdtRepo.quote, PaykitAmount.parse.
Call sites traced: openOnchainConfirmForInvoiceAmount (one, after the balance and dust checks), navigateToAmountFromConfirm, Routes.UsdtPayment (built only by handleUsdtPaymentInput).
CI: build-local and Greptile green; build-and-test, lint, compose-ui and the local e2e shards still running when this was posted.
Ruled out
- Confirm skips a step Amount's Continue does: for auto coin selection
prepareCoinSelectionreturns true with no side effect,selectedUtxosis already null after the reset, the hardware fee is prepared before navigating, andrefreshOnchainSendIfNeededfollows; Lightning routing estimation does not apply to an on-chain pay method. - Manual coin selection or a contact payment reaching Confirm without the picker: both return false before any state change and fall through to Amount, covered by the manual-coin-selection test.
- Back loops or strands the sheet: from the main scanner the stack becomes
[Amount]and Amount's Back hides the sheet; from the send sheet it becomes[Recipient, ..., Amount]; after Continue, Back pops to Amount through the existingpopBackStack(SendRoute.Amount)branch.canReturnToAmountlives inSendUiState, so every new send clears it throughresetSendState. - Amount loses the invoice amount on the way back:
SendAmountScreenseeds its input fromuiState.amountwhen it is positive. - A hardware fee estimate failure: it toasts and returns false, then the scan falls through to Amount, the same place it went before.
- USDT quote repeats on rotation or process death:
isRequestedis saveable and the effect is keyed onUnit, so Back, Edit and a restore never quote again;canQuoteguards a busy state. - USDT amount string rejected by the quote: the route amount is
PaykitAmount.value(a plain dot decimal), which bothPaykitAmount.parseInputandUsdtRepo.quoteaccept, the same string the Review button sends.
Merge confidence: 4/5, not built here and CI still running; the e2e send suite expects Amount for this route until the bitkit-e2e-tests change named in the PR lands.
Regtest APKDownload bitkit-dev-debug universal APK (expires in 30 days). |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
System Back on a Confirm opened straight from a system-back-from-confirm.mp4 |
coreyphillips
left a comment
There was a problem hiding this comment.
Two independent reviews.
needs changing before merge
- E2E send shard breaks: e2e main still expects Amount for BIP21 with amount (app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt:5402)
worth doing, does not block
- USDT journey clipboard step still says the amount screen opens (journeys/usdt-payment-links-and-scans.xml:6)
- Hardware-wallet direct-Confirm path has no test (app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt:5426)
- Tapping the amount on direct Confirm does nothing (app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt:5434)
- The PIN journey expects Home one Back press too early (journeys/security/pin-lock-on-resume.xml:45-46)
nits
- KDoc on a private function (app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt:5415-5418)
pwltr
left a comment
There was a problem hiding this comment.
Reviewed commit 1d280b6c59a51ede602149b453981acf160656b7 through general, security and cross-platform source review, followed by targeted finding verification.
[P2] Tapping the amount cannot edit it after opening confirmation directly
For a valid amount-bearing Bitcoin request with Autopilot coin selection, the new flow opens Confirm without adding Amount to the navigation stack. Tapping the amount still emits BackToAmount, which becomes PopBack(Amount). SendSheet.kt only calls popBackStack for that effect, so the tap silently does nothing when Amount is absent.
The new fallback is wired to toolbar/system Back, which remains a workaround, but the amount-edit control does not use it. Route that control through the same fallback, or explicitly open Amount when it is missing. This is an introduced navigation regression confirmed by source tracing; it does not itself submit a payment.
Review details
General review
Model: Claude Opus 5.5
Reasoning effort: xhigh
Security review
Model: Kimi K3
Reasoning effort: max
Cross-platform review and verification
Model: GPT-6.1-sol
Reasoning effort: xhigh
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Replying to the review on 1d280b6:
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review round 7 (d00e77c). Pixel 9 emulator, dev build of d00e77c, wallet with no USDT.
r7-usdt.mp4 |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review round 8 (156f029). Pixel 9 emulator, dev build of 156f029, wallet with no USDT. USDT was switched off again afterwards.
r8-usdt.mp4
Tests: |
pwltr
left a comment
There was a problem hiding this comment.
Reviewed commit 156f029.
Medium candidate — fixed-amount contact payment may become stuck on Amount. If the Paykit SDK delivers an on-chain-only contact endpoint containing a positive-amount Bitcoin URI, the app locks that amount before initializing its validity. For a Savings-only user, Continue can then remain disabled; switching to a funded hardware wallet provides a recovery path. Initialize validation before locking the amount or preparing the Amount screen. The application-side path is supported statically, but whether the pinned SDK delivers this endpoint shape remains unverified; this is a conditional candidate, not a reproduced production failure.
Review details
General review: GPT-6.1 Sol / high (Codex).
Finding verification: GPT-6.1 Sol / high (Codex).
pwltr
left a comment
There was a problem hiding this comment.
Correction: my request for changes on this point was premature. The scenario depends on the Paykit SDK returning an amount-bearing BIP21 URI for a contact endpoint, which I haven’t verified.
Please treat this as a non-blocking question pending confirmation that the SDK supports that input. I’m withdrawing it as a reason to block this PR.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Dismissing: the one point still open was the e2e send shard on bitkit-e2e-tests main. synonymdev/bitkit-e2e-tests#290 now provides the same-name fix/scan-amount-to-confirm branch, and the e2e send shard passed on head 6a85db25.
|
@jvsena42 Merging: approved on the head, CI green including the e2e send shard, and every review thread resolved. synonymdev/bitkit-e2e-tests#290 can merge right after, so e2e main matches both apps; the iOS twin synonymdev/bitkit-ios#1198 is already merged. |

Twin: synonymdev/bitkit-ios#1198
Companion: synonymdev/bitkit-e2e-tests#290 — updates
send.e2e.tsfor this route; the e2e gate needs it, so merge them together.This PR:
Motivation, from the Slack report:
Description
uint256=0counts as no amount.fixed-price-bitcoin.xmland the payment-requests README, which still described the Amount detour.Out of Scope
viewmodels/AppViewModel.kt: a unified BIP21 whose Lightning invoice has no amount but whose on-chain part does keeps opening Amount on Spending.send.e2e.tsexpectations for on-chain BIP21 with an amount are updated in test: expect review screen for bip21 with an amount bitkit-e2e-tests#290.Design
N/A — no design available.
Preview
On-chain BIP21 with an amount, opened as a link, goes straight to Confirm; tapping the amount stays on Confirm and Back closes the sheet. A below-minimum link shows Amount Too Low:
r6-dust-link.mp4
The same URI entered through Send → Enter Manually opens Confirm:
onchain-amount-manual-entry.mp4
BIP21 without an amount still opens Amount:
onchain-no-amount-to-amount.mp4
Manual coin selection: the link opens Confirm and the swipe opens the coin picker:
r6-manual.mp4
USDT link with an amount opens the fixed review; with no USDT the quote error and Try Again show there:
r6-usdt.mp4
Fixed 2.50 USD Paykit request with USDT off goes from Preparing straight to Confirm at 2 500 sats:
paykit-usd-request-to-confirm.mp4
QA Notes
Setup
Dev regtest build from this branch on an emulator, against the staging regtest backend the dev flavor targets, with a wallet holding about 700 000 sats in Savings and a Lightning channel. Coin Selection on Autopilot. The Paykit cases used the
paykit-fixture-senderfrom bitkit-e2e-testsmain, linked to a Pubky profile created on the payer. USDT cases enable USDT through the link's prompt; the wallet has no USDT balance.Journeys
scan-onchain-amount-to-confirm.xml— BIP21 with an amount opens Confirm directly, tapping the amount stays on Confirm, Back leaves Confirm without opening Amount, over-balance and below-minimum amounts show their toastsscan-onchain-no-amount-to-amount.xml— BIP21 without an amount, or with amount 0, still opens Amountusdt-payment-links-and-scans.xml— a USDT link or copied URI with an amount opens review without tapping Review, or shows the quote error on that review; Back returns to the recipient stepfixed-quoted-confirmation.xml— a fixed USD request accepting Bitcoin and USDT opens Bitcoin Confirm with USDT offfixed-price-bitcoin.xml— fixed-price requests open confirmation directly with 21 000 and 50 000 satsonchain-accepted-result.xml— the fixed-amount send starts on Confirmrbf-own-send.xml— the boosted send starts on Confirmpin-lock-on-resume.xml— the payment URI opened while locked opens Confirm after unlock; Back closes the sheetsignin-with-second-link.xml— the payment link opens Confirm once the sign-in sheet closesmanual-coin-selection.xmlandmanual-coin-selection-load.xml— with manual coin selection the link opens Confirm and the swipe opens the coin pickerManual Tests
N/A
Automated Checks
AppViewModelSendFlowTest.kt— on-chain BIP21 with an amount opens Confirm from the main scanner and from Send, including with manual coin selection; no amount opens Amount; a dust amount shows the minimum without opening Send; a hardware wallet's fee is estimated before Confirm and a failed estimate keeps the user on the address; a hardware wallet that covers what Savings cannot is selected; switching to Savings restores the scanned amount; a speed change keeps a scanned hardware amount; a fixed USD request accepting USDT opens Bitcoin Confirm while USDT is offUsdtWalletScreenTest.kt— the initial quote runs only with a recipient and a positive amount; a positive requested amount is fixed and zero is not; the fixed amount stays with the recipient that set it./gradlew testDevDebugUnitTest,./gradlew detektand./gradlew lintDevDebugpassed locally; CI green on 6a85db2Evidence
Verified on a Pixel 9 emulator (API 37) with the dev debug build of this branch:
uint256=0as no amount, Back then Continue keeping a USDT amount fixed: fix: open review for requests with an amount #1763 (comment)bitcoin:<addr>and?amount=0open Amount at 0; entering 10 000 continues to Confirm.usdandbtcpresets open Confirm at 21 000 and 50 000 sats.amount=0.00001opens Confirm at 1 000 sats with Savings and the recipient.Gaps
signin_grantURLs. Its Confirm step follows the same PIN-gated link route verified in J8.@send_1and@send_2are updated in test: expect review screen for bip21 with an amount bitkit-e2e-tests#290 on the same-named branch the e2e gate picks up; all E2E shards passed against it on 6a85db2.Models used
claude-opus-5-5(reasoning: Not exposed)claude-opus-5-5(reasoning: Not exposed)The reasoning setting is not exposed in this session's metadata.
🤖 Generated with Claude Code