feat: add Paykit server accounts#1084
Conversation
Greptile SummaryThis PR adds Paykit Server watch-only accounts. The main changes are:
Confidence Score: 5/5No additional blocking issue was found in this follow-up.
|
| Filename | Overview |
|---|---|
| app/src/main/java/to/bitkit/ui/screens/profile/PubkyAuthApprovalViewModel.kt | Adds the watch-only consent and companion-claim authorization flow. |
| app/src/main/java/to/bitkit/repositories/WatchOnlyAccountRepo.kt | Adds account preparation, tracking, activation, cancellation, and restore operations. |
| app/src/main/java/to/bitkit/data/WatchOnlyAccountStore.kt | Adds persistent account, allocation, backup, and reconciliation state. |
| app/src/main/java/to/bitkit/services/LightningService.kt | Adds LDK configuration and reconciliation for watch-only accounts. |
Reviews (3): Last reviewed commit: "fix: derive Paykit Noise key from wallet..." | Re-trigger Greptile
601cdaa to
3e1064d
Compare
dccbfe3 to
f0bfb2e
Compare
32b8c1d to
6782574
Compare
|
Reviewed this against the companion iOS PR and paykit-server (ADR 0001 / 0002 + README). UI gatingSettings → Advanced → Server Accounts is always visible today. Please hide it behind Enable Paykit UI (same pattern as Payment Preferences / other Paykit surfaces), so this unfinished server flow doesn’t show up for default users. How to test / blockerFull happy-path QA needs a real Paykit Server setup Scanner/paste → watch-only consent → authorize → account appears under Server Accounts → external fund of claimed xpub → restart/scan → spend → disable/re-enable tracking. That path isn’t available end-to-end right now: paykit-server is not runnable (README: partial implementation; Questions:
Without that, we can only review code/UI structure + unit coverage; not the live setup → claim → track → fund path. Other notes
CI / mergeMerge conflicts with the base branch ( Happy to re-test once there’s a setup URL path (or staging) and the above are addressed. |
5050c1e to
edb688f
Compare
|
Thanks — the app-side items are now addressed on the latest commit. UI gatingSettings → Advanced → Server Accounts is now only visible when Enable Paykit UI is enabled. Testing the flowReviewers can exercise the Bitkit-side flow using this disposable request: Enable Paykit UI, then paste or scan it. This exercises:
A requester does not need to remain connected: Paykit uploads both relay messages and Bitkit activates the account after both deliveries succeed. From Server Accounts, the reviewer can copy the xpub, derive a nonzero external address, fund it, restart Bitkit, spend the discovered funds, and test disabling/re-enabling tracking. Because the URL contains a public test secret, it should only be used with a disposable regtest wallet. What this does not verify is requester-side polling, decryption, and signature verification of the claim. That still requires a Paykit Server listener or receiver harness. Server stagingThe intended next server-side QA step is to deploy Paykit Server on staging once its runtime/listener composition is implemented. There is no staging endpoint yet, and that work is outside these mobile PRs. Retry and activation behaviorThe post-delivery cases are covered:
This behavior is covered by the repository and approval ViewModel tests. Protocol versionADR 0001's Regression and CIThe branch was rebased onto the latest stacked base and is currently mergeable. The full Android unit suite, Detekt, builds, and all current E2E checks pass, including the staging |
# Conflicts: # app/src/test/java/to/bitkit/repositories/BackupRepoTest.kt # app/src/test/java/to/bitkit/repositories/LightningRepoTest.kt # app/src/test/java/to/bitkit/viewmodels/AppViewModelSendFlowTest.kt
|
Retested after the alignment fixes. Settings nits look good (icon/casing, drawer burger). Limiting Blocking: home Scan still rejects Tab bar Scan opens Send, not a main scanner: onScanClick = { appViewModel.showSheet(Sheet.Send(SendRoute.QrScanner)) }Gate is: private val isMainScanner get() = currentSheet.value !is Sheet.SendSo home Scan → Send paste / Send scan / Enter manually rejecting Please:
|
|
Thanks for the thorough cross-platform retest. Items 1–4 were addressed in Android commit
Focused coverage was added for the identity states and Send/global-scanner routing. Ordinary Pubky Auth remains unchanged. Thanks also for confirming the complete xpub funding/spending and tracking lifecycle. We’ve noted the Electrum timeout observation. Since both platforms recovered correctly through retry and it did not prevent receive/spend, we’re treating it as a backend-load observation rather than a blocker for this PR. The two subsequent inline review items were addressed in |
As I mentioned in #1084 (comment), home scan currently blocks Screen.Recording.2026-07-24.at.10.40.35.mov |
|
Fixed in The home scan button now opens the global scanner via I also updated the regression test to exercise the real global scanner-sheet path ( Verified with:
|
jvsena42
left a comment
There was a problem hiding this comment.
tAck
Screen_recording_20260724_081015.webm
@ben-kaufman please, force-push or squash the commits with verified signature |


Description
This PR builds on #1066 to add Paykit Server watch-only accounts:
x-bitkit-claim=watch-only-account-v1and the exact/pub/paykit/v0/bitkit/server/:rwcapability, rejecting missing, unknown, duplicate, or mismatched companion parameters.approveAuthWithCompanionClaim, failing closed if companion delivery or normal authorization fails.0.1.0-rc37, LDK Node0.7.0-rc.57, and Bitkit Core0.4.2; Bitkit Core now supplies trusted extended-public-key serialization, so BitcoinJ is no longer required.The relay claim contains only the versioned account index, address type, and serialized xpub. Local names and tracking state are not disclosed. Ordinary Pubky Auth remains unchanged.
References:
QA Notes
This slice implements ADR 0001's
watch-only-account-v1claim, which is the currently agreed protocol. ADR 0002's proposedwatch-only-account-service-v1delegation flow has not been agreed and is not part of the current implementation.Reviewers can exercise the complete Bitkit-side setup and account lifecycle with this disposable test request:
Enable Paykit UI, then scan or paste the URL. It exercises watch-only consent, normal Pubky authorization, account allocation and xpub export, companion-claim delivery followed by AuthToken delivery, local activation, and Server Accounts management. The xpub can be copied from the account details and used for external address derivation, funding, restart discovery, spending, and tracking disable/re-enable testing.
The request secret is public, so this URL must only be used with a disposable regtest wallet. A Paykit Server listener or receiver harness is still required to verify requester-side relay polling, decryption, and signature verification. A staging deployment is intended once Paykit Server runtime/listener composition is available.
Manual Tests
Automated Checks
WatchOnlyAccountClaimCodecTest.ktWatchOnlyAccountStoreTest.ktWatchOnlyAccountRepoTest.ktWatchOnlyAccountLifecycleCoordinatorTest.ktWatchOnlyAccountRestoreTest.ktPubkyAuthApprovalViewModelTest.ktPubkyAuthRequestTest.ktPubkyRepoTest.ktLightningServiceTest.ktPaykitSdkServiceTest.ktPrivatePaykitRepoTest.kt./gradlew testDevDebugUnitTest./gradlew detekt(passes with unrelated existing findings)