Files
amethyst/.claude/skills/account-state/references/account-state-flow.md
T
Claude f72388a559 refactor: rename packages, helpers and app code after the NIP event renames
Follow-up to the event class renames: the names around those classes now
match too.

Quartz (published API, every old name kept as a @Deprecated alias/forwarder):
- nip51Lists packages moved: followList -> starterPack, hashtagList -> interestList,
  peopleList -> followSet, labeledBookmarkList -> bookmarkSet. The old packages
  keep a Deprecated.kt with typealiases and forwarding extension functions
  (ReplaceWith points at the new package).
- LnZapPrivateEvent -> PrivateZapEvent, LnZapReceiptValidator -> ZapReceiptValidator,
  ChannelListDiff -> PublicChatListDiff, HashtagListDiff -> InterestListDiff.
- Kind 30063 now indexes NIP-82 release notes for search (never NIP-51 content,
  which can hold encrypted private items). searchable-events docs updated.

App code (amethyst, commons, desktopApp, cli; no aliases needed):
- model packages nip51Lists.{hashtagLists,peopleList,labeledBookmarkLists,relayFeeds}
  -> {interestLists,followSets,bookmarkSets,favoriteRelays}.
- State/cache/UI names derived from the old event names: HashtagListState ->
  InterestListState, PeopleListsState -> FollowSetsState, FollowListsState ->
  StarterPacksState, LabeledBookmarkList -> BookmarkSet, RelayFeedListState ->
  FavoriteRelayListState, ContactCardsState -> UserAssertionsState, NIP90* view
  models/renderers -> Dvm*, LnZap* handlers -> Zap*, SealedRumor* -> Seal*, and
  Account.peopleLists/followLists/hashtagList -> followSets/starterPacks/interestList.
- String literals were left untouched, so preference keys and @SerialName values
  stored on disk are unchanged.
- The generic PeopleList UI model (shared by follow sets and starter packs) and the
  EmojiPackSelection route (which shows a kind 30030 pack) keep their names.

Docs: plans, brainstorms, changelogs, skills and READMEs use the new names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015VvJ8XpeYqBe8bYT3bJ7UD
2026-09-26 20:56:07 +00:00

5.6 KiB

Account State-Object Catalog

Account.kt composes ~50 feature state objects (not raw StateFlow properties). Each object pins its backing addressable note in LocalCache, exposes val flow: StateFlow<…> (decrypted + backup-merged + stateIn), and offers suspend mutation helpers that return signed events. Consumers read account.<property>.flow.

(Property and class names are exact as of the current Account.kt; if one has been renamed, grep Account.kt for the class name.)

Identity & Contacts

Account property State class Kind Package
userMetadata UserMetadataState 0 amethyst/.../model/nip01UserMetadata/
kind3FollowList Kind3FollowListState 3 model/nip02FollowLists/
muteList (+ muteListDecryptionCache) MuteListState 10000 model/nip51Lists/muteList/
blockPeopleList, peopleLists BlockPeopleListState, FollowSetsState NIP-51 people sets model/nip51Lists/followSets/
followLists StarterPacksState NIP-51 follow sets model/nip51Lists/followSets/
hiddenUsers HiddenUsersState — derived from muteList.flow + blockPeopleList.flow — model/nip51Lists/
allFollows MergedFollowListsState — merges kind3 + people/follow/hashtag/geohash/community lists — model/serverList/

Relay Lists

Account property State class Kind Package
nip65RelayList Nip65RelayListState 10002 model/nip65RelayList/
dmRelayList DmRelayListState 10050 model/nip17Dms/
searchRelayList SearchRelayListState 10007 model/nip51Lists/searchRelays/
blockedRelayList BlockedRelayListState 10006 model/nip51Lists/blockedRelays/
localRelayList LocalRelayListState local model/localRelays/
privateStorageRelayList PrivateStorageRelayListState private storage model/edits/
keyPackageRelayList, trustedRelayList, proxyRelayList, broadcastRelayList, indexerRelayList, favoriteRelayList per-feature …RelayListState classes, each with a DecryptionCache sibling custom relay sets model/nip51Lists/…

Derived relay views (merge several of the above): homeRelays (AccountHomeRelayState), outboxRelays, dmRelays, notificationRelays, trustedRelays, followPlusAllMineWithIndex, followPlusAllMineWithSearch, defaultGlobalRelays.

Content Lists

Account property State class Kind Package
bookmarkState (and legacy oldBookmarkState) BookmarkListState 10003 model/nip51Lists/
bookmarkSets BookmarkSetsState NIP-51 bookmark sets model/nip51Lists/bookmarkSets/
pinState PinListState NIP-51 model/nip51Lists/
interestSets InterestSetsState NIP-51 interest sets model/nip51Lists/interestSets/
hashtagList / geohashList InterestListState / GeohashListState NIP-51 model/nip51Lists/interestLists/, …/geohashLists/
communityList CommunityListState NIP-72 communities model/nip72Communities/
favoriteAlgoFeedsList FavoriteAlgoFeedsListState NIP-51 model/nip51Lists/
emoji, ownedEmojiPacks EmojiPackState, OwnedEmojiPacksState 10030 commons/.../commons/model/nip30CustomEmojis/
publicChatList PublicChatListState NIP-28 commons/.../commons/model/nip28PublicChats/
ephemeralChatList EphemeralChatListState ephemeral chats commons/.../commons/model/emphChat/
blossomServers BlossomServerListState Blossom (BUD) model/nipB7Blossom/

Other Feature State

Account property State class Purpose Package
vanish VanishRequestsState NIP-62 vanish requests model/nip62Vanish/
appSpecific AppSpecificState NIP-78 app data model/nip78AppSpecific/
otsState OtsState NIP-03 OpenTimestamps model/nip03Timestamp/
live*FollowListsPerRelay OutboxLoaderState(...).flow — already a flow per-feed outbox routing model/topNavFeeds/
privateDMDecryptionCache, draftsDecryptionCache PrivateDMCache, DraftEventCache NIP-44 decryption caches —

Note the migration direction: newer/extracted state classes live in commons/src/commonMain/.../commons/model/, the rest still in amethyst/src/main/java/.../model/. Check both when looking for one.

Publishing Mutations

State objects' mutation helpers (e.g. MuteListState.hideUser(pubkey), BookmarkListState add/remove) build and sign the updated replaceable event via the quartz event class (XEvent.add / remove / create) and return it. The caller (usually a method on Account) is responsible for sending it through the client. Decryption results are cached in the paired …DecryptionCache so re-renders don't re-decrypt.

When a State Object Doesn't Exist Yet

If you're adding a new NIP that's user-scoped, follow the pattern (full recipe in SKILL.md):

  1. Create model/nipXX…/XState.kt modeled on MuteListState (encrypted) or BookmarkListState (plain).
  2. Pin the note with cache.getOrCreateAddressableNote(...), expose val flow: StateFlow<…> via stateIn(scope, Eagerly, default).
  3. Instantiate it in Account.kt (plus a DecryptionCache sibling if private), and wire the relay subscription (see relay-client skill).
  4. Add mutation helpers that build, sign, and return the event; publish from the calling site.
  5. Use AccountSettings for the local backup copy if the list must survive relay loss.