You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Cancelling a hardware-wallet signature for an incoming Paykit payment request leaves the request stuck. The payer keeps showing the request as being paid, and the requester waits forever for a payment that will never arrive.
AppViewModel.prepareHardwareContactPayment() (app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt:4345) accepts the payment request and consumes the private payment list before the Trezor is asked to sign. When the user then declines on the device, onHardwareSignCancelled() (AppViewModel.kt:4365) only flips isSubmittingPaymentRequest = false:
Nothing tells the proof side that the started on-chain payment failed, so the accepted request is never rolled back.
Dismissing the Send sheet mid-sign is worse: hideSheet() never calls onHardwareSignCancelled() at all, so it takes the same path with no cleanup whatsoever.
Expected behavior
Cancelling on the device — or dismissing the sheet while the hardware signature is pending — should fail the started payment proof, so the request returns to an actionable state on both sides.
Steps to Reproduce
Enable Paykit (Dev Settings toggle) on two devices and pair them as contacts.
Pair a Trezor on the payer.
On the payee: drawer → REQUESTS → Request Payment → pick the payer → Send Request.
On the payer: drawer → REQUESTS → Show Details → set FROM to the Trezor wallet → Swipe To Pay.
On the hardware-sign screen, decline the signature on the Trezor (or dismiss the sheet).
The request stays in its accepted/paying state; the requester never sees a rejection.
Additional context
Scope: only reachable when Paykit payment requests are enabled, and only for the hardware funding source. Regular (non-HW) sends unwind correctly.
A fix already exists but is not on master: commit ae762113f ("fix: clean up cancelled hardware payments") on branch codex/paykit-subscriptions-android (PR feat: add Paykit subscriptions #1186). It adds PaykitPaymentProofRepo.failOnchainPayment, routes both onHardwareSignCancelled() and the hideSheet() path through a shared cancelHardwarePaymentRequestIfNeeded(), and covers both with tests in AppViewModelSendFlowTest.kt. Either land feat: add Paykit subscriptions #1186 or cherry-pick that commit.
Found while reviewing master (452757987) for release readiness.
What happened?
Cancelling a hardware-wallet signature for an incoming Paykit payment request leaves the request stuck. The payer keeps showing the request as being paid, and the requester waits forever for a payment that will never arrive.
AppViewModel.prepareHardwareContactPayment()(app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt:4345) accepts the payment request and consumes the private payment list before the Trezor is asked to sign. When the user then declines on the device,onHardwareSignCancelled()(AppViewModel.kt:4365) only flipsisSubmittingPaymentRequest = false:Nothing tells the proof side that the started on-chain payment failed, so the accepted request is never rolled back.
Dismissing the Send sheet mid-sign is worse:
hideSheet()never callsonHardwareSignCancelled()at all, so it takes the same path with no cleanup whatsoever.Expected behavior
Cancelling on the device — or dismissing the sheet while the hardware signature is pending — should fail the started payment proof, so the request returns to an actionable state on both sides.
Steps to Reproduce
Additional context
master: commitae762113f("fix: clean up cancelled hardware payments") on branchcodex/paykit-subscriptions-android(PR feat: add Paykit subscriptions #1186). It addsPaykitPaymentProofRepo.failOnchainPayment, routes bothonHardwareSignCancelled()and thehideSheet()path through a sharedcancelHardwarePaymentRequestIfNeeded(), and covers both with tests inAppViewModelSendFlowTest.kt. Either land feat: add Paykit subscriptions #1186 or cherry-pick that commit.master(452757987) for release readiness.🤖 Generated with Claude Code
https://claude.ai/code/session_012WLdYvhLGXZxj9hktuLraE