Skip to content

Gift Wrapped DMs with NDKDirectMessage and NDKChatroom #327

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

manimejia
Copy link
Contributor

@manimejia manimejia commented May 9, 2025

This PR adds backward compatible Direct Messages and Chatrooms, supporting both NIP-17 (giftwrapped) and NIP-04 (legacy) direct messages.

class NDKDirectMessage

  • extends NDKEvent as a single class to support all types of direct message
  • can be instatiated from (and published as) either a kind 04 OR a kind 1059 (gift wrapped) nostr event.
  • calls NDKDirectMessageRelays.for(NDKUser) to fetch and cache user preferences for DM relays (as per NIP-17)

class NDKChatroomThread

  • local cache for decrypted messages
  • groups messages by 'thread' (matching author and recipient pubkeys)
  • satisfies the NIP-17 specification for 'chatroom' (with a better name)

class NDKChatroom

  • chatrooms are a collection of one or more threads, managed by the end user
  • chatroom default 'subject' is last message with 'subject' tag (as per NIP-17 spec)
  • chatroom 'subject' can be customized by end user (overriding the default)
  • chatroom 'readuntil' stores the timestamp of 'last read' message
  • chatroom metadata can be exported (as json) for use across browsers sessions

class NDKChatroomController

  • main interface for subscribing to and management of chatroom instances.
  • subscribes to all kind 4 and 1059 events for a given user and filter.
  • decrypts new messages into 'threads' and creates a new 'chatroom' for each new thread.
  • provides a 'subscribable' (Svelte store) interface for 'chatrooms' (as per RxJS Observables)
  • notifies chatroom subscribers whenever chatroom metadata or messages are updated

usage

  • instantiate NDKChatroomController : const controller = new NDKChatroomController(ndk)
  • start subscription : const chatrooms = controller.subscribe()
  • send direct message : const newmessage = controller.sendMessage(recipients, content, subject, kind)
  • render chatrooms UI in svelte : {#each $chatrooms as chatroom}...
  • render messages UI in svelte : {#each chatroom.messages as message}...

TODO

  • FIX : utf8Encoder() is unavailable from nostr-tools (as imported from ndk), for use in method getThreadId()
  • ADD : unit tests

testing

  • works on local
  • no test authored as yet...

manimejia added a commit to manimejia/nips that referenced this pull request May 10, 2025
Specifies updated conventions for Direct Message Chatrooms in  NIP-17.  

addresses issue nostr-protocol#1297 

implemented in recent [PR for NDK](nostr-dev-kit/ndk#327)
@manimejia
Copy link
Contributor Author

I'm squashing some bugs. Please hold on testing...

…ew features

Various updates and bug fixes, still not quite ready for prime time...

FIXME kind 4 messages sent by client user (from this or other clients) are not being decrypted properly when recieved back from relays by this client ... but other messages are fine ... and other clients render these messages fine also.

FIXME fetching messages from relays is slow and some messages are not fetched at all ...
@manimejia
Copy link
Contributor Author

I've made a number of updates, and now these two modules are running alongside NDK, as part of my onboarding client, nostrmeet.me.

There are still a few improvements needed before this is ready for NDK integration. I will continue to make tweaks, but here are two rather vexing issues that I prolly need some help with:

  1. Kind 4 messages authored by client user (from any client) are not being decrypted. Witness this issue by signing into the private messages view of my onboarding client. All other kind 4 and 14 messages are encrypted and decrypted fine. The same kind 4 messages sent by client user are decrypted fine on other other clients. Nos2x extension throws Error: nos2x: aes/pcks5: wrong padding byte:NUMBER. I suspect this has something to do with either pubkey or content being passed to signer.decrypt(pubkey,content,'nip04') from event.decrypt() in NDK, but I have not gotten to the bottom of this.
  2. utf8Encoder is not being imported properly from nostr-tools. This is used as part of the hashing routine when creating ID's for threads and chatrooms. Hashing is needed to hide user identities when chatrooms are stored offline, because an array of pubkeys is used for the ID of each thread. Importing and using utf8Encoder works fine when these modules run directly in my client code, but when included as part of NDK utf8Encoder is not found by TS compiler during build.

Here are these two modules as used in my client code.

Here is the svelte store in my client that instantiates NDKChatroomSubscriber

Here is the component in my client that makes use of the stores

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