Skip to content

feat: add profile and contacts fetching from pubky#476

Open
ben-kaufman wants to merge 27 commits intomasterfrom
feat/pubky-profile
Open

feat: add profile and contacts fetching from pubky#476
ben-kaufman wants to merge 27 commits intomasterfrom
feat/pubky-profile

Conversation

@ben-kaufman
Copy link
Copy Markdown
Contributor

@ben-kaufman ben-kaufman commented Mar 5, 2026

Summary

Integrates Pubky decentralized identity into Bitkit, allowing users to create a Bitkit-managed profile or connect via Pubky Ring authentication. Once connected, the user's profile name and avatar appear on the home screen header, a full profile page shows their bio, links, tags, and shareable QR code, and a contacts section lists people they follow on the Pubky network.

What's included

  • Dual profile creation flow — create a new profile from BIP39 seed derivation, or import via Pubky Ring deep links (pubkyauth://)
  • Profile restore — when creating a profile, if one already exists on the network for the derived keys, it is detected and pre-populated (name, bio, links, tags preserved)
  • Ring auth import flow — after Ring authentication, discover existing profile and contacts from pubky.app, present import overview with "Import all" or "Select" options, then proceed to Pay Contacts onboarding
  • Pay Contacts onboarding — new step after both create and Ring import flows, with toggle for sharing payment data
  • Profile page displaying name, bio, links, tags, and a QR code with the profile picture overlaid
  • Profile editing — edit name, bio, links, and tags with suggestion sheets for links and tags
  • Contacts list with alphabetically grouped sections, search, add, edit, and delete
  • Contact detail page showing name, truncated public key, bio, links, tags, and copy/share/edit/delete actions
  • Contact import — overview screen showing found profile & contacts count with avatar stack, selection screen with select all/none, batch import
  • Home screen integration showing the authenticated user's name and avatar in the header
  • Session restoration — automatic re-sign-in using stored secret key when session import fails (Bitkit-managed); session preserved on failure for retry on next launch (Ring-managed); toast notification when restoration fails
  • PubkyService — service layer wrapping paykit-ffi (profile/contacts/payments) and bitkit-core (auth relay, PKDNS file fetching, key derivation)
  • PubkyProfileManager — manages auth state, session lifecycle, key derivation, profile creation/editing, and remote profile fetching
  • ContactsManager — fetches contacts in parallel via withTaskGroup, groups alphabetically, supports add/edit/delete/import, discovers remote contacts from pubky.app
  • PubkyImage component for loading pubky:// URIs with two-tier (memory + disk) caching
  • PubkyProfileData backward-compatible decoding — tags field defaults to empty array when missing from JSON (older profiles, other clients)
  • Suggestion card auto-dismiss when user is already authenticated
  • QR component — moved QR code generation off the main thread

New dependencies

  • paykit-rs (SPM, pinned revision) — Pubky SDK for profile, contacts, and payment operations
  • CoreBluetooth framework (linker flag, required by paykit-rs)

Key new files

File Purpose
Services/PubkyService.swift FFI bridge to paykit-ffi and bitkit-core
Managers/PubkyProfileManager.swift Auth state, session persistence, key derivation, profile CRUD
Managers/ContactsManager.swift Contact fetching, import, add/edit/delete, remote discovery
Models/PubkyProfile.swift Profile/contact data models with backward-compatible decoding
Models/PubkyAuthRequest.swift Auth request capability parsing
Components/PubkyImage.swift pubky:// image loader with disk+memory cache
Views/Profile/ProfileView.swift Full profile page (name, bio, links, tags, QR)
Views/Profile/CreateProfileView.swift Profile creation with restore detection
Views/Profile/EditProfileView.swift Profile editing
Views/Profile/PayContactsView.swift Pay Contacts onboarding step
Views/Profile/PubkyChoiceView.swift Create vs Ring import choice
Views/Profile/PubkyRingAuthView.swift Pubky Ring auth flow UI
Views/Profile/AddLinkSheet.swift Add link with suggestions
Views/Profile/AddProfileTagSheet.swift Add tag with suggestions
Views/Contacts/ContactsListView.swift Grouped, searchable contacts list
Views/Contacts/ContactDetailView.swift Contact detail with actions
Views/Contacts/ContactImportOverviewView.swift Import overview (profile + contacts summary)
Views/Contacts/ContactImportSelectView.swift Selectable contact list for import
Views/Contacts/AddContactView.swift Add contact by public key
Views/Contacts/EditContactView.swift Edit contact details
Views/Sheets/PubkyAuthApproval/PubkyAuthApprovalSheet.swift Auth approval as authenticator
BitkitTests/PubkyModelTests.swift Tests for profile/contact models and data decoding
BitkitTests/PubkyProfileManagerTests.swift Tests for HomegateResponse decoding
BitkitTests/PubkyAuthRequestTests.swift Tests for capability parsing

Test plan

  • Fresh install: tap Profile in drawer → shows intro → continue → choice screen (Create / Import with Ring)
  • Create flow: Create Profile → enter name, pick avatar → Continue → Pay Contacts → Profile page
  • Create restore: If profile already exists for derived keys, name is pre-populated and title shows "Restore Profile"
  • Ring flow: Import with Ring → opens Pubky Ring → approve → returns to Bitkit → Import Overview (found profile & contacts) → Import All or Select → Pay Contacts → Profile page
  • Ring flow (no contacts): If no remote contacts found, skip import and go to Pay Contacts
  • Import select: Can select all, select none, or pick individual contacts; Continue with none selected skips import
  • Profile page shows name, bio, links, tags, QR code with profile picture overlay
  • Edit profile: tap edit → modify name/bio/links/tags → save → updated
  • Home header shows profile name and avatar after authentication
  • Kill and relaunch app → session restored, profile/contacts shown without re-auth
  • Kill and relaunch with no network → session preserved, toast shown, next launch with network restores
  • Sign out from profile page → returns to unauthenticated state, contacts cleared
  • Contacts list shows "My Profile" row, alphabetical sections, search, and add button
  • Add contact by public key → fetches profile → saves
  • Edit contact → modify details → save
  • Delete contact → confirmation → removed
  • Suggestion sheets for links and tags show lightbulb icon inside input field

🤖 Generated with Claude Code

@ovitrif ovitrif added this to the 2.2.0 milestone Mar 9, 2026
@ovitrif ovitrif changed the title Feat: add profile fetching from pubky feat: add profile fetching from pubky Mar 10, 2026
ovitrif
ovitrif previously approved these changes Mar 11, 2026
Copy link
Copy Markdown
Collaborator

@ovitrif ovitrif left a comment

Choose a reason for hiding this comment

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

LGTM with some nit comments.

all tests worked great, tested:

  • open profile from topbar + drawer
  • 2x auth successes
  • button to download ring
  • share pk button(s)
  • signout button

@claude

This comment has been minimized.

- Profile creation with restore flow (detects existing remote profile)
- Ring auth flow with contact import overview and selection screens
- Pay Contacts onboarding step after profile creation and Ring import
- Session restoration with re-sign-in recovery, preserving session on failure
- Toast notification when session restoration fails
- Lightbulb icon and tag suggestion button placement fixes
- Edit profile error message fix
- PubkyProfileData backward-compatible decoding (tags field defaults to [])
- New tests for PubkyProfileData encoding/decoding

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ben-kaufman and others added 6 commits March 31, 2026 16:29
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Show "Loading your profile…" instead of "Waiting for authorization…"
once Ring approves, and hide the cancel button during data fetch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v0.1.53's Package.swift references v0.1.54 binaries which don't exist.
v0.1.52 correctly references its own release binaries.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PubkyAuthDetails.kind is now PubkyAuthKind enum instead of String.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

6 participants