feat: add private payment requests - #1172
Conversation
This comment has been minimized.
This comment has been minimized.
ba7f745 to
e8183a5
Compare
5120677 to
7877465
Compare
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
af0aaa4 to
e2516e9
Compare
|
Flagging while QA’ing with the staging public-pay pubkys — not a prod issue (Paykit UI is still hidden). Enabling payments with contacts fail-closes with Unknown error if a saved contact’s receiver marker doesn’t parse (here: missing
In principle the same thing could happen with any broken / outdated profile marker, not only these fixtures. Recording attached. Same surface on iOS after #676 (toast there is Private Paykit is not available). Steps:
Screen.Recording.2026-08-26.at.10.12.34.mov |
|
Flagging from QA: paying a payment request that’s larger than the wallet balance. Same setup, two directions, both recordings attached:
Screen.Recording.2026-08-26.at.14.06.24.mov
Screen.Recording.2026-08-26.at.14.18.16.movSteps:
Expected: don’t enter confirm if the amount is above spendable. On Android, Dismiss should still work after a failed Pay (no already in progress loop). |
|
Addressed both QA findings in signed commit
The matching iOS fixes are isolated in synonymdev/bitkit-ios#684: malformed remote markers no longer block other contacts, and incoming request amounts are used during initial LN/on-chain balance validation so the standard insufficient Spending/Savings error appears before coin selection. Local verification: 193 focused Android tests passed; detekt completed successfully with only unrelated pre-existing findings. |
|
Retested after 5d39cd9. Enable — still fails. ❌ Toggle Enable payments with contacts → Unknown error, toggle does not stay on. Same staging contact as before ( This is not the Same user-facing miss on iOS #684 (toast there is Private Paykit is not available). Steps:
Screen.Recording.2026-08-27.at.10.24.05.-.android.movOver-balance — looks good on Android. ✅ Incoming request larger than the wallet: one Insufficient Savings / Spending toast, request stays pending and dismissible. No already in progress loop. iOS #684 still repeats that toast (see that PR). |
jvsena42
left a comment
There was a problem hiding this comment.
Code review
Reviewed git diff master...HEAD at 56ce990 (merge-base 6ae3cb7) — 34 files, ~3.8k added lines. 10 findings inline, roughly in severity order: the ReceiveSheet start-destination change and the dropped firstError in PrivatePaykitRepo look like the two most likely to bite in practice.
Checked and looked correct: the generation/identity guards in PaykitPaymentRequestRepo (activate/refresh/synchronizeLocked/isCurrentState), creationMutex.tryLock with finally unlock in propose, expiration rescheduling, the hideSheet re-entrancy guard, SheetHost's confirmValueChange + rememberUpdatedState pairing, the scrim's pointer-consuming modifier, the stopped/recursion loop in presentNextIncomingPaykitPaymentRequest, and the sats/BTC BigDecimal conversions.
One judgement call I did not flag as a defect: the string-literal match in canDeferStaleSession is brittle against SDK message changes.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
56ce990 to
531578e
Compare
|
Addressed the remaining enable/disable QA path in signed, rebased commit 531578e. The private setting now reflects the user choice independently of transient transport cleanup or immediate Noise availability:
Regression coverage includes deferred disable cleanup, re-enable with pending cleanup, recovery without a marker, failure after remote cleanup but before local pruning, and total versus partial marker-selection failure. The over-balance behavior that passed the retest is unchanged. Post-rebase verification: full testDevDebugUnitTest, detekt, and compileDevDebugAndroidTestKotlin pass. The stack is rebased onto current master and all 13 PR commits are signed. |
This PR adds private Paykit Payment Requests to Bitkit.
Description
0.1.0-rc44and adds local E2E homeserver configuration plus safe cold-start restoration for externally managed Pubky sessions.The request payload itself remains SDK-backed and durable; Bitkit persists only encrypted, identity-scoped presentation suppression, not a duplicate request queue. Payment proofs and receipts remain out of scope.
Dependencies:
41cda2567226a690a012770017d5e7c1d49e2a2b.Preview
N/A — proof recordings were completed locally and are intentionally not attached to the PR.
QA Notes
Manual Tests
Automated Checks
PaykitPaymentRequestRepoTest.kt: covers mapping, eligibility, proposal delivery, rejection, expiry, identity-scoped presentation state, and action serialization.PaykitSdkServiceTest.kt: covers exact identity enforcement and safe deferred session restoration.AppViewModelSendFlowTest.kt: covers automatic/manual presentation, sheet transitions, identity changes, newer-list retry, strict private resolution, and payment lifecycle races.PaymentRequestExpirationTest.kt: covers expiry selection and retained draft state.SheetHostTest.kt: covers locked sheet dismissal and scrim input isolation during durable proposal creation.git diff --check.