Skip to content

fix: adopt paykit 0.1.1-rc6 - #1803

Draft
ben-kaufman wants to merge 13 commits into
masterfrom
chore/paykit-rc6
Draft

ben-kaufman wants to merge 13 commits into
masterfrom
chore/paykit-rc6

Conversation

@ben-kaufman

@ben-kaufman ben-kaufman commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Twin: synonymdev/bitkit-ios#1237

This PR:

  1. Updates Paykit to 0.1.1-rc6
  2. Measures Payment Proofs with the SDK before paying, for USDT and now also for Lightning and on-chain Payment Requests
  3. Explains a Payment Request note that is too long to send
  4. Explains a signup code the homeserver refuses, and network errors, during Pubky authorization
  5. Stops counting a USDT transfer made well before its Payment Request as paying it

Description

  • Pins com.synonym:paykit-android to 0.1.1-rc6, the same one-line change as earlier Paykit bumps. The bump itself only needed test fixtures for the new Payment Request record times and the private list acknowledgement field.
  • Uses paymentProofEventLen to measure the largest Payment Proof Bitkit would send, so the check matches what the SDK queues instead of a hand-built JSON copy. A proof that would not fit one Paykit message is refused before anything is paid, because it could never reach the payee. USDT already had this check. Lightning and on-chain Payment Request payments, manual and automatic, now have it too. An automatic Allowance payment measures before it accepts the request, so an oversized one stays manual instead of being accepted and then failing to pay.
  • Shows "Shorten the note and try again." when the SDK reports a one-time Payment Request as too large to send (a long note in a multi-byte script can do this). A subscription proposal the SDK finds too large shows the existing subscription message.
  • Shows "The homeserver did not accept this signup code. Try again or use another signup link." for a refused signup code, and "Check your connection and try again." for network errors, instead of "Unknown error" on the Pubky authorization sheet.
  • Flags a USDT receipt whose verified transfer time is more than 24 hours before the payee recorded the request (the Arbitrum timestamp bound) as "Received · Before request". It no longer counts as paying the request or a subscription period, as the Paykit payment time rule asks. The funds are still received.
  • Sign-up and sign-in already handle rc6's new error categories: network failures now arrive as transport errors, which session restore already treats as temporary, and an identity that lives on another homeserver already falls back to sign-in. Tests now pin both.
  • Notes for release: rc6 writes Paykit shared state and SDK backups in a newer format. Once an rc6 build writes them, builds on rc5 or older cannot read them, so Android and iOS should ship this together. rc6 also checks Encrypted Link write slots before publishing (one extra request per send) and has the Pubky HTTP client trust only the webpki-roots 1.0.11 list. The staging and production homeserver, relay, pkarr and homegate hosts all chain to ISRG Root X1, which that list includes.

Out of Scope

  • PaykitAllowanceRepo: accepting a contact's pending allowance offers with acceptPendingAllowanceProposals. The bulk call also accepts offers Bitkit does not list, such as non-BTC terms, and drops the per-proposal binding, so offers are still accepted one at a time. iOS made the same call.
  • Profile removal: original-grant observation and logout from Paykit rc3 and rc4 belong to fix: bind profile removal to its original owner #1693.
  • Contact removal: it still blocks the peer when withdrawing the private list reports a failure. Unchanged here.
  • Profile creation from the wallet seed: a refused Homegate signup code still falls back to sign-in, so the signup code message only shows in the signup link flow.
  • Subscription acceptance: the Acceptance is sent before any proof size check, so a third-party payee whose Payment Reference is too long for a proof only fails at the first payment. References Bitkit creates cannot hit this. iOS has the same gap.
  • Signup link flow: a sign-up refused because the identity lives on another homeserver still shows the generic authorization error. No new copy for it here.

Design

N/A - no design available.

Preview

N/A

QA Notes

Setup

  • Dev (regtest) build of this branch. It resolves com.synonym:paykit-android:0.1.1-rc6 from GitHub Packages (AAR SHA-256 792ace22d4e188733df3ec3644d69e22fb6692f39115ce55b706f91edc3ccdd8).
  • J1 uses two Bitkit instances on this build, saved as each other's contacts and linked as identities, as in request-summary.xml. Put the 256 "💜" note on the requester's clipboard, since adb shell input text cannot type emoji.
  • J2 needs a controlled requesting app that produces a pubkyauth://signup_grant URL whose signup token the homeserver refuses, for example the token of a link another wallet already completed, and a wallet with no Pubky identity. See the pubky-auth suite README.
  • Manual 1 needs the linked fixture issuer from the payment-requests suite, sending a one-time BTC request with a Payment Reference long enough that its Payment Proof would not fit 1000 bytes (about 700 bytes of reference).
  • Manual 2 needs the local USDT fixture from docs/usdt-qa.md and a payer that submits a Payment Proof for a USDT transfer made more than 24 hours before the request.

Journeys

  • J1: new request-note-too-long.xml - a note too long for one Paykit message is refused with "Shorten the note and try again." before anything is sent, and the request sends once the note is shortened
  • J2: new grant-signup-rejected-code.xml - a refused signup code shows its own message, keeps the sheet open and creates no identity

Manual Tests

  • 1. Fixture issuer sends a one-time BTC request with a near-limit Payment Reference → Pay → "Payment request is unavailable" shows and nothing is paid - an issuer request with a custom Payment Reference length not in Capabilities
  • 2. USDT payee receives a proof for a transfer made more than 24 hours before the request → Payment Requests → the row shows "Received · Before request" and the request is not shown as paid - a payer proving an older USDT transfer not in Capabilities
  • 3. Device offline → open a signup link → Authorize → "Check your connection and try again." shows - toggling device network not in Capabilities

Automated Checks

  • updated PaykitPaymentProofRepoTest.kt - a Lightning proof is measured with its largest preimage, app and allowance before payment, an on-chain proof too large for one message is refused before payment, and a proof the SDK cannot measure is refused as unavailable
  • updated PaykitAllowanceExecutorTest.kt - the proof is measured with the Allowance ID before automatic acceptance, and a request whose proof would not fit stays manual without acceptance
  • updated PaykitUsdtPaymentRepoTest.kt - the USDT proof is measured by the SDK with the largest valid receipt log index (fits and too large). Transfers within the 24 h tolerance pay the request and older ones are flagged and do not
  • updated PaykitPaymentStateBackupTest.kt - a USDT backup without the new flag still decodes, and the flag round trips
  • updated AppViewModelSendFlowTest.kt - a request too long to send shows "Shorten the note and try again." and does not complete
  • updated PaykitPaymentRequestRepoTest.kt - message_too_large maps to the note error, and other protocol errors pass through unchanged
  • updated PaykitPaymentRequestRepoSubscriptionTest.kt - an SDK message_too_large maps to the subscription message
  • updated PubkyAuthErrorMessageTest.kt - refused signup codes and transport errors get their own text, and other identity errors keep the fallback
  • updated PubkyRepoTest.kt - a sign-up refused because the identity lives elsewhere signs in, and a transport failure does not sign up again
  • updated PaykitIssuerInteropTest.kt, PrivatePaykitRepoTest.kt, PaykitSdkServiceTest.kt - fixtures for the new rc6 record and report fields
  • removed PaykitUsdtPaymentRepoTest.kt boundary cases for the hand-built proof JSON - the SDK now does the measurement
  • ran openssl s_client -showcerts against httprelay, homeserver, pkarr and homegate (production and staging), pkarr.pubky.org and relay.pkarr.org - every chain ends at ISRG Root X1

Evidence

  • 7cc585b5: just compile, just test and just lint pass locally (4,955 unit tests in 264 suites, 0 failures or skips, 0 detekt findings, 0 Android Lint issues).
  • The rc6 AAR resolved from GitHub Packages after the paykit-rs Gradle Package release run succeeded.

Gaps

  • J1, J2 and Manual 1 to 3 were not run by the author. Device and emulator runs were out of scope for this change. Reviewers run the device gates.
  • The shared journeys have the same <action> steps as the iOS twin (chore: adopt Paykit 0.1.1-rc6 bitkit-ios#1237), apart from platform identifiers.

Models used

  • Planning/scoping: Claude Opus 5.5 (reasoning: Not exposed)
  • Implementation: Claude Opus 5.5 (reasoning: Not exposed)
  • Review: Claude Opus 5.5 (reasoning: Not exposed)
  • Review rounds: 1

The session metadata does not expose a reasoning setting.

🤖 Generated with Claude Code

ben-kaufman and others added 13 commits November 6, 2026 11:42
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>
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>
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>
@github-actions

github-actions Bot commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

Regtest APK

Built from 7cc585b (run).

Download bitkit-dev-debug universal APK (expires in 30 days).

This branch has not been deployed

No deployments
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.

1 participant