Skip to content

feat(profile,chat): profile pictures + tip DM service-layer support#1106

Merged
bmc08gt merged 2 commits into
code/cashfrom
feat/flipcash-profile-and-tip-dm
Jul 20, 2026
Merged

feat(profile,chat): profile pictures + tip DM service-layer support#1106
bmc08gt merged 2 commits into
code/cashfrom
feat/flipcash-profile-and-tip-dm

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

Builds out the net-new (P3) service-layer features enabled by the flipcash proto sync (#1105). Two commits, two coherent bundles:

  1. feat(profile) — profile pictures
  2. feat(chat,resolver) — tip DM support

No UI is wired yet; this is the service/domain/persistence plumbing the upcoming features will consume.

Profile pictures

  • SetProfilePicture RPC scaffolded across the stack: ProfileApiProfileServiceProfileRepository/InternalProfileRepositoryProfileController, with a SetProfilePictureError sealed type covering every proto result (DENIED, BLOB_NOT_FOUND, BLOB_NOT_READY, BLOB_REJECTED, INVALID_BLOB). The response blob.v1.Media maps to the domain MediaItem.
  • UserProfile.profilePicture propagated end-to-end: domain model, UserProfileMapper, the inline chat-member profile builder, and persistence (UserProfileSerialized + compat DTO + entity mappers).

Tip DMs

  • buildTipDmPaymentMetadata() builds the intent AppMetadata for a user-id↔user-id tip payment (no phone source/destination).
  • Resolver by user ID via the resolver Identifier.user_id arm. The Identifier oneof is modeled as a domain ResolveIdentifier (Phone | UserId), so ResolverApi/ResolverService/ResolverRepository each expose a single resolve(owner, identifier) — the phone-vs-user-id branch lives in exactly one place (proto construction). ResolverController keeps two ergonomic entry points (resolve(phone) / resolveByUserId(userId)) that delegate to it, so existing callers (e.g. ContactCoordinator) are unchanged.
  • getDmChatFeed(chatType) now takes a required ChatType so callers filter CONTACT_DM vs TIP_DM explicitly (threaded through Api/Service/Repo/Controller). No default — the server maps a missing/UNKNOWN value to CONTACT_DM, so a silent default would hide intent. Feed sync passes CONTACT_DM, preserving current behaviour.

Tests

  • New UserProfileMapper cases for profile-picture mapping (present + absent).
  • New ChatController test asserting the chat-type filter is forwarded; existing feed tests updated for the required param.
  • Test doubles updated (FakeProfileRepository, FakeChatRepository, chat-coordinator mocks).

Verification

:services:flipcash:testDebugUnitTest, :apps:flipcash:shared:chat:testDebugUnitTest, and :apps:flipcash:shared:persistence:db:testDebugUnitTest all pass; :apps:flipcash:shared:contacts (the resolve(phone) caller) compiles.

Deferred

UI consumers, and actually consuming EventStreamingController.blobUpdates for upload-completion, remain for the feature work that builds on this.

Scaffold the SetProfilePicture RPC across the service layer (Api -> Service ->
Repository -> Controller) with a SetProfilePictureError sealed type covering the
proto result cases (DENIED, BLOB_NOT_FOUND/NOT_READY/REJECTED, INVALID_BLOB). The
response's blob.v1.Media is mapped to the domain MediaItem.

Propagate the new UserProfile.profile_picture field: add UserProfile.profilePicture
(MediaItem), map it in UserProfileMapper and the inline chat-member profile builder,
and persist it via UserProfileSerialized (+ compat DTO and the entity mappers).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions github-actions Bot added type: feature New functionality area: network gRPC, connectivity, API, exchange rates labels Jul 20, 2026
@bmc08gt
bmc08gt force-pushed the feat/flipcash-profile-and-tip-dm branch from 6ee493f to 1b1bf53 Compare July 20, 2026 22:13
Wire up the service-layer pieces for tip DMs introduced by the proto sync:
- buildTipDmPaymentMetadata() builds the intent AppMetadata for a tip DM payment
  (user-id to user-id, no phone source/destination)
- ResolverController.resolveByUserId() resolves a user ID to their on-chain
  address via the resolver Identifier.user_id arm, added through Api/Service/Repo
- getDmChatFeed now takes a required ChatType so callers filter explicitly for
  CONTACT_DM vs TIP_DM (threaded through Api/Service/Repo/Controller). No default,
  so intent is always stated; feed sync passes CONTACT_DM to preserve behaviour.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@bmc08gt
bmc08gt force-pushed the feat/flipcash-profile-and-tip-dm branch from 1b1bf53 to fa15872 Compare July 20, 2026 22:17
@bmc08gt
bmc08gt merged commit afb95a1 into code/cash Jul 20, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: network gRPC, connectivity, API, exchange rates type: feature New functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant