Skip to content

feat: add profile and contacts fetching from pubky#476

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

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

Conversation

@ben-kaufman
Copy link
Contributor

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

Summary

Integrates Pubky decentralized identity into Bitkit, allowing users to connect their Pubky profile 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, and shareable QR code, and a contacts section lists people they follow on the Pubky network.

What's included

  • Authentication flow via Pubky Ring deep links (pubkyauth://) with relay-based session exchange, session persistence in Keychain, and automatic restoration on app launch
  • Profile page displaying name, bio, links, and a QR code with the profile picture overlaid
  • Contacts list with alphabetically grouped sections, search, and a "My Profile" header row
  • Contact detail page showing a contact's name, truncated public key, bio, links, and copy/share actions
  • Home screen integration showing the authenticated user's name and avatar in the header
  • PubkyService — service layer wrapping paykit-ffi (profile/contacts/payments) and bitkit-core (auth relay, PKDNS file fetching)
  • PubkyProfileManager — manages auth state, session lifecycle, and profile data with all FFI/Keychain/disk operations offloaded to background threads
  • ContactsManager — fetches contacts in parallel via withTaskGroup, groups them alphabetically, and resets on sign-out
  • PubkyImage component for loading pubky:// URIs with two-tier (memory + disk) caching
  • 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)

New files

File Purpose
Services/PubkyService.swift FFI bridge to paykit-ffi and bitkit-core
Managers/PubkyProfileManager.swift Auth state, session persistence, profile loading
Managers/ContactsManager.swift Contact fetching, parallel profile loading, alphabetical grouping
Models/PubkyProfile.swift Profile data model with placeholder factory
Components/PubkyImage.swift pubky:// image loader with disk+memory cache
Views/Profile/ProfileView.swift Full profile page (name, bio, links, QR)
Views/Profile/PubkyRingAuthView.swift Pubky Ring auth flow UI
Views/Contacts/ContactsIntroView.swift Contacts onboarding screen
Views/Contacts/ContactsListView.swift Grouped, searchable contacts list
Views/Contacts/ContactDetailView.swift Contact detail (bio, links, copy/share)

Modified files

File Change
AppScene.swift Inject PubkyProfileManager and ContactsManager, initialize Paykit early, eager-load contacts on auth
MainNavView.swift Wire up profile/contacts/auth navigation routes
Header.swift Show profile name + avatar, navigate to profile
Suggestions.swift Auto-dismiss profile card when authenticated
QR.swift Async QR generation via .task(id:)
Info.plist LSApplicationQueriesSchemes for pubkyauth, ATS config
Keychain.swift Add paykitSession entry type
NavigationViewModel.swift Add .pubkyRingAuth, .contactsIntro, .contactDetail(publicKey:) routes
ProfileIntro.swift Updated layout and styling
Colors.swift Add pubkyBrand color
Localizable.strings Profile and contacts translation keys

Test plan

  • Fresh install: tap Profile in drawer → shows intro → continue → auth screen
  • Auth screen: shows "Download Pubky Ring" if Ring not installed, "Authorize" if installed
  • Authorize → opens Pubky Ring → approve → returns to Bitkit → navigates to profile page
  • Profile page shows name, bio, links, QR code with profile picture overlay
  • Home header shows profile name and avatar after authentication
  • Kill and relaunch app → session restored, profile/contacts shown without re-auth
  • Sign out from profile page → returns to unauthenticated state, contacts cleared
  • Profile suggestion card auto-dismisses when authenticated
  • Fresh install: tap Contacts in drawer → shows intro → continue → auth screen (if not yet authenticated)
  • After authenticating via Profile or Contacts intro → contacts list loads automatically
  • Contacts list shows "My Profile" row, alphabetical sections, and search
  • Search filters by name or public key; "My Profile" row hides during search
  • Tap a contact → detail page shows name, truncated key, bio, links
  • Copy button copies full public key; share button opens system share sheet
  • Contacts with no profile show a placeholder name (truncated public key)
ScreenRecording_03-04-2026.23-49-21_1.MP4

@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
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.

@piotr-iohk
Copy link
Collaborator

Some observations (on version before force-push, as the current is not building):

  • authorize when no pubky ring installed results in App error, (in Android there is a popup message informing pubkyring not installed with option to download)
Screen.Recording.2026-03-16.at.12.37.15.mov
  • same as Android: "Hardcoded production domains — no staging support"
  • same as Android: Unrecoverable "Unable to load profile" state. Although restoring wallet is a workaround that resolves the "Unable to load profile" state unlike in Android

@piotr-iohk
Copy link
Collaborator

piotr-iohk commented Mar 16, 2026

Same thing with staging as for Android: synonymdev/bitkit-android#824 (comment)

... and then same as synonymdev/bitkit-android#824 (comment) ✅ :)

@ovitrif
Copy link
Collaborator

ovitrif commented Mar 16, 2026

What are the plans for landing this, 2.2 is correct?

@pwltr This is indeed what we agreed on afterward-ish the sprint planning: unless someone sees an issue with it. We ship this without the announcements, as it's just adding some niceyiness to users who like to explore, without really enabling any small part of the bigger picture yet.

So it's just aesthetics from user's pov FWIW, but app is nicer and more friendly than without it ( (ie: I can see my profile picture at the top of the app if I auth with my pubky).

ovitrif
ovitrif previously approved these changes Mar 16, 2026
Copy link
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.

Re-approving from my side, still worth considering & addressing the remaining remarks from teammates 🙏🏻 , but nothing we can't solve in a new PR imo

@ben-kaufman
Copy link
Contributor Author

Everything should be fixed, e2e tests issue not related, it fails the same way on other PRs too cc @piotr-iohk

@piotr-iohk
Copy link
Collaborator

Everything should be fixed, e2e tests issue not related, it fails the same way on other PRs too cc @piotr-iohk

Yes, there is some divergency, because v60 redesign is merged on iOS and not merged on Android yet.

@pwltr
Copy link
Contributor

pwltr commented Mar 17, 2026

What are the plans for landing this, 2.2 is correct?

@pwltr This is indeed what we agreed on afterward-ish the sprint planning: unless someone sees an issue with it. We ship this without the announcements, as it's just adding some niceyiness to users who like to explore, without really enabling any small part of the bigger picture yet.

So it's just aesthetics from user's pov FWIW, but app is nicer and more friendly than without it ( (ie: I can see my profile picture at the top of the app if I auth with my pubky).

Currently the UX is very poor for users that are not on pubky.app yet (probably >90% of users). Since you can't create a profile from Bitkit and you can't signup to the Synonym homeserver from within Pubky Ring without an invite code (it says to ask the Synonym team?) you just get stuck in somewhere along the flow without any hand holding. That is after going to the app store and downloading an additional app which can be argued is also not explained clearly enough as to why it is necessary.

Not sure what the solution will be but imo this is not a good experience and doesn't add anything for most users.

Simulator.Screen.Recording.-.iPhone.17.-.2026-03-17.at.10.27.05.mov

@aldertnl
Copy link

For additional guidance on scroll behavior, see this prototype demo recording:
https://github.com/user-attachments/assets/edd73093-0404-4061-af31-6cf865565a08

@ovitrif
Copy link
Collaborator

ovitrif commented Mar 17, 2026

Currently the UX is very poor for users that are not on pubky.app yet (probably >90% of users). Since you can't create a profile from Bitkit and you can't signup to the Synonym homeserver from within Pubky Ring without an invite code (it says to ask the Synonym team?) you just get stuck in somewhere along the flow without any hand holding. That is after going to the app store and downloading an additional app which can be argued is also not explained clearly enough as to why it is necessary.

Not sure what the solution will be but imo this is not a good experience and doesn't add anything for most users.

[recording]

Thanks for the insights @pwltr, it looks to me that any of the possible solutions require extra work.

Remaining options:

  1. Use feature flags to merge this sooner
  2. Keep this work on a feature branch
  3. Require team to find a resolution
    1. address the issues with current broken flow for users without a pubky.app account
    2. brainstorm on release plans
    3. etc

Out of the 3 above, the option of feature flags seems more straightforward and with the most predictable outcome.

Wdyt?

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.

5 participants