Skip to content

feat: add private payment requests - #676

Open
ben-kaufman wants to merge 7 commits into
masterfrom
codex/paykit-payment-request-ui
Open

feat: add private payment requests#676
ben-kaufman wants to merge 7 commits into
masterfrom
codex/paykit-payment-request-ui

Conversation

@ben-kaufman

@ben-kaufman ben-kaufman commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

This PR adds private Paykit Payment Requests to Bitkit.

Description

  1. Automatically opens incoming requests in the existing Send confirmation flow with the requesting contact, exact amount, and a Payment Request title.
  2. Keeps dismissed requests actionable through a bell, preview sheet, and full request history, with manual reopen and explicit rejection.
  3. Adds outgoing request creation from Receive for linked, saved contacts, including amount, note, expiry, queued delivery state, and sent history.
  4. Drops expired or remotely unavailable requests, keeps presentation state scoped to the active Pubky identity, and protects account changes and overlapping actions.
  5. Requires strict private resolution for requests: a consumed Private Payment List is never reused, another endpoint from that list is not attempted, and public details are never used as fallback while waiting for a newer list.
  6. Updates Paykit to 0.1.0-rc44 and 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 identity-scoped presentation suppression, not a duplicate request queue. Payment proofs and receipts remain out of scope.

Dependencies:

Linked Issues/Tasks

N/A

Screenshot / Video

N/A — proof recordings were completed locally and are intentionally not attached to the PR.

QA Notes

Manual Tests

  • 1. Clean wallet → create Pubky profile → enable Paykit and Contact Payments → add the peer as a contact: private-capable request action appears once the Noise link is established.
  • 2. Peer creates a private request → Home: Payment Request opens automatically with the correct contact and amount.
  • 3. Payment Request → dismiss without rejecting → bell → request preview → Pay: the request remains queued, reopens, and pays successfully.
  • 4. Peer creates a second request after payment → Pay: a newer Private Payment List is used; the consumed list is not reused and no public fallback occurs.
  • 5. Receive → Send Payment Request → enter amount, note, and expiry → select linked contact → Send: request is queued once and appears in sent history.
  • 6. Incoming request → Reject: only that request becomes terminal and the private payment list is not consumed.
  • 7. Incoming request → dismiss → relaunch: request remains discoverable without automatically reopening again; expired requests disappear live.
  • 8. Cross-platform E2E: Android creates two requests that iOS receives and pays, and iOS creates two requests that Android receives and pays, on clean regtest state.

Automated Checks

  • BitkitTests/PaykitPaymentRequestServiceTests.swift: 46 tests cover mapping, eligibility, proposal delivery, rejection, expiry, identity isolation, presentation races, queue durability, fresh-list retry, and action reconciliation.
  • BitkitTests/PaykitSdkClientConfigTests.swift: 4 tests cover production/local configuration and safe deferred session restoration.
  • Focused test run: 50 tests passed on the iOS simulator.
  • SwiftFormat lint passed for all 20 changed Swift files.
  • Translation validation passed with 0 errors.
  • Both final cross-platform proof videos decoded end to end without errors.

@greptile-apps

greptile-apps Bot commented Aug 20, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds SDK-backed private payment-request creation, receipt, presentation, rejection, history, and identity-scoped suppression, alongside Paykit session-restoration and local E2E configuration changes.

  • Adds incoming-request discovery and automatic/manual Send-flow presentation.
  • Adds outgoing request composition, recipient eligibility checks, queued delivery, and sent history.
  • Adds request expiration, rejection, retry, concurrency, and identity-isolation state management.
  • Updates Paykit to 0.1.0-rc44 and expands focused service/configuration tests.

Confidence Score: 5/5

The PR appears safe to merge, with no concrete changed-code defect established by the reviewed request, identity, and presentation flows.

The request lifecycle validates active identity and recipient eligibility, reconciles actions against authoritative SDK state, scopes presentation suppression by identity, and guards overlapping presentation and creation operations.

Important Files Changed

Filename Overview
Bitkit/Services/PaykitPaymentRequestService.swift Adds incoming and outgoing request mapping, recipient eligibility, proposal/rejection operations, identity-scoped presentation persistence, retries, expiry, and action reconciliation.
Bitkit/AppScene.swift Integrates identity activation, recipient refresh, automatic request presentation, and Send-sheet lifecycle reconciliation.
Bitkit/Services/PubkyService.swift Adds payment-request SDK methods and deferred recovery from stale externally managed Pubky sessions.
Bitkit/ViewModels/SheetViewModel.swift Adds payment-request sheet configuration and replacement-state coordination for delayed sheet transitions.
Bitkit/Views/PaymentRequests/CreatePaymentRequestView.swift Implements amount, note, expiry, recipient selection, submission, and delivery-result UI.
Bitkit/Views/PaymentRequests/PaymentRequestsView.swift Implements pending previews, full incoming and sent history, manual payment reopening, and rejection.
BitkitTests/PaykitPaymentRequestServiceTests.swift Extensively covers mapping, delivery, eligibility, expiration, identity isolation, concurrency, retries, and reconciliation.

Sequence Diagram

sequenceDiagram
    participant Peer
    participant SDK as Paykit SDK
    participant Manager as PaymentRequestManager
    participant UI as Bitkit UI
    participant Send as Send Flow

    Peer->>SDK: Private payment request
    Manager->>SDK: Synchronize private messages
    SDK-->>Manager: Actionable incoming requests
    Manager-->>UI: Pending request notification
    UI->>Manager: Open request
    Manager->>SDK: Resolve private payment details
    SDK-->>Manager: Private endpoint or retry state
    Manager->>Send: Present exact amount and contact
    Send->>Manager: Accept request
    Manager->>SDK: Accept and queue response
    Manager-->>UI: Remove request from pending history
Loading

Reviews (1): Last reviewed commit: "feat: add private payment requests" | Re-trigger Greptile

@ben-kaufman
ben-kaufman force-pushed the codex/paykit-payment-request-ui branch from 7ef6f37 to 1604cb7 Compare August 20, 2026 11:41
ovitrif
ovitrif previously approved these changes Aug 20, 2026

@ovitrif ovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved. Incoming private requests open in Send with the requesting contact and exact amount, dismissed requests stay reopenable until reject or expiry, and a consumed Private Payment List is never reused or replaced by public details.

@ovitrif ovitrif added this to the 2.5.0 milestone Aug 20, 2026
@ben-kaufman
ben-kaufman requested a review from piotr-iohk August 21, 2026 01:08
@ben-kaufman
ben-kaufman force-pushed the codex/paykit-payment-request-ui branch from ad1803b to 5756057 Compare August 21, 2026 01:15
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.

2 participants