Dm3 - decentralized messaging for web3

Thanks a lot for your great feedback!

Is the salt supposed to be a secret too? Is it app specific? In the case that the user wants to use a second client to read his dm3 messages, do they need the salt too or will the new app just generate a new key with a new salt? In that case, we would need to list multiple public keys so that the user could receive messages in many devices.

The salt isn’t supposed to be a secret. It’s always stored unencrypted together with the encrypted payload (messages, contact list, …). The following snippet shows the typings of a storage object:

  version: string;
  salt: string; // unencrypted randomly generated string
  payload: string; // encrypted user storage

If the app retrieves the storage JSON file, it will read the salt property and ask the user to sign the salt with his wallet. The signature will then be used to derive the key to decrypt the payload. This way, the wallet owner will always be able to decrypt a storage object. We did it this way because MetaMask deprecated eth_decrypt and eth_getEncryptionPublicKey. The good thing about not using eth_decrypt and eth_getEncryptionPublicKey is that we are not bound to MetaMask anymore.

So, if a user wants to load his messages on a second device/client, he just needs to load the storage file and sign the salt with his wallet.

It is also possible to export the encryption key. The export makes it possible to use dm3 on a device without access to the Ethereum private key. For example, if you used dm3 at first on your desktop computer and now you also want to use it on another device but you don’t want to put your ethereum private key there. Therefore you just need to scan a QR code representation of the encryption key with the new device.

Any service could decide to be the server of the user’s messages. Is there a standard way for one service to retrieve messages from the other? I would suggest that every DM3 compatible service should have an API that returns an (encrypted?) RSS feed with messages for/from any user. This way messages could be replicated among many services, if the user so desires

The user selects the delivery service he wants to use by putting it into his profile which can be accessed by querying the eth.dm3.profile ENS Text Record of the user. If I want to send a message to a specific user, the dm3 app will look up the URL of the delivery service this user is using and send the message there. The delivery service just buffers incoming messages until they are delivered. After the messages are delivered, the delivery service will delete the message (similar to pop3 for email). If the dm3 app instance retrieves the message, it will store it at the storage location the user selected (browser storage, local file, ipfs, google drive or dm3 storage service). This way, the user has complete control over the location of his data.

I agree it would make sense for the dm3 storage service to provide an API method to move the complete user storage of one user to another dm3 storage service instance or a completely other storage location. I created an issue for that

I see some very different applications that would require slightly different implementations: one to one private chats, group private chats, and social media posts (both public and within a given audience). Do you see the same protocol as serving all of these?

I think most of the use cases you mentioned should be possible to realize with just minor changes on the protocol side. For example, I implemented a public message feed demo version of dm3. In this case, the delivery service would store the feed and make it publicly available. So if your dm3 app instance would like to get my public feed, it would look up the eth.dm3.profile ENS text record of hai-ko.eth. There it would find the URL to my delivery service and my public signing key. Then the app would query the delivery service to get the feed and check the signatures of every message in the feed. The public messages would then be shown to you if the signatures are valid.


This is great! Loved your detailed presentation here and on the Ecosystem call @hai-ko.eth.

I just used dm3 for the first time and it was honestly a really good experience! Your approach to messaging reminds me of the sufficient decentralization approach that Farcaster takes to social protocols, which I’m personally a big fan of.

A few questions/pieces of feedback came to mind:

  • I assume the eth.ens-mail text record has to be on my primary ENS name so that dm3 knows where to look. What happens if I change my primary ENS name after first signing in to dm3?
  • Is there an implementation of a delivery service handling notifications for an incoming message? I’d love to see a demo of that since notifications seem to be one of the biggest problems with web3 messaging products.

  • I first signed into dm3 on my phone, then went to sign in with the same wallet on my computer. As a piece of feedback, I thought it was confusing that the sign-in screen includes the option to select a storage destination. It feels like that should be a later screen after the user has signed in. Also, I think people would feel a lot more comfortable signing this message if it had a description like some of the earlier prompts.

As far as integrations go, it would be cool if you allowed dapps to apply custom styling to the embedded chat. I think this would make it a lot easier to convince devs to integrate dm3. Rainbowkit does this really well as an example.

Excited to see where you take this!


I really appreciate the thought and effort that went into creating dm3.

Can you help me understand if this would work for wallet to wallet communication, if both parties do not have ENS name? I realize you can send messages to any address, however what takes the place of the ens text record?

Would non-ens communication necessitate the creation of on-chain registry to serve the purpose that ens text records are used for?

I have a few other thoughts that will take a bit of time to articulate well, please bear with me in the meantime.


The protocol you’re building seems super cool! Looks like you’re taking a Farcaster-style “sufficiently decentralized” approach, all makes sense to me. :slightly_smiling_face:

For what it’s worth, though, while I think ENS DAO should support this project with resources, I don’t think it would be wise for TNL to integrate a chat solution into the main frontend at this time. We need to see which protocol actually gets any traction, it’s far too early to choose a winner, imo.

1 Like

In order to communicate via dm3 you need to look up an address’s profile data (public messaging key, public signing key, and delivery service URL, which may not be one of dm3’s). I see no better place to store that info than as an ENS record…

Although you can use the protocol without an ENS name, it would only work within the confines of a single delivery service. So if you create your dm3 profile using the dm3 delivery service / storage, then you’ll only be able to send messages to accounts using the same dm3 delivery service. Other delivery services would not have the profile data for that account!

I would even say that the dm3 protocol should require an ENS name. It streamlines and future-proofs things, and ensures better decentralization, so that you don’t end up with a few large siloed, walled-garden providers. Not sure what @hai-ko.eth thinks though


Fully +1 on this perspective. If you don’t use ENS, you’ll end up using something that’s similar but bespoke, so might as well use ENS.

Thank you @gregskril for your feedback!

I wasn’t aware of Farcaster but you are right the basic concept is similar.

Yes, as you assumed during sign-in, dm3 looks up the primary ENS name (reverse record) for the selected address. If you change this and sign in, you will get an empty inbox, but I think this is ok because changing your ENS name is like changing your identity. Maybe there should be a method to migrate the message storage in case of a primary ENS name change.

The current version has no support for notifications, but I’m working on it. The current idea is that you can register notification alerts (email, SMS,…) on the delivery service.

During the initial sign-in, the app needs to ask the user where the messages should be stored, but I think it would make sense that the delivery service remembers the storage location of a user. In this case, you only have to select the storage location once during the initial sign-in. It could also be possible to set for example, the browser storage as default and that the user has to change it if they wish.

Absolutely I have to change this.

That’s already possible. The react component has a style property, but I’ll have a look at Rainbowkit maybe I can improve it.


I think it is a good idea to require an ENS name, but I wouldn’t go so far as to require the user to create the dm3 ENS text record during the initial sign-in because I think it would impact adoption negatively if users are forced to send a transaction before they can use the protocol. @serenae as you mentioned, the users are currently able to interact with other users on the same delivery service without sending a transaction. I think if the users try it out and then want to interact with users on other delivery services or switch themself to another delivery service, they are more willing to send a transaction.

1 Like

Looks like an awesome project and from what I can see, very well thought through!

If you ever require some help on the UI / Graphic design side of things, please feel free to message me!

I am involved in the ENS community working creatively with some other dev teams and projects and always love to collaborate.

Are you guys in the ENS builders discord ? If not I would suggest checking it out. Great people there.

@BrianMillsJr.Eth is your guy to talk to!

Good work !


You could also look for metadata stored directly on the user’s reverse record, and if you don’t find it there, check the primary name.

How do I add metadata directly to the user’s reverse record? I thought the reverse records are only for mapping from an Ethereum address to an ENS name. Could I just add a text record to a subdomain of addr.reverse like bcd6de065fd7e889e3ec86aa2d2780d7553ab3cc.addr.reverse?

That’s right. Reverse records use the same resolver system, so you can set text records on them. The default resolver used by the reverse registrar doesn’t support them, but you can set a custom one - and when we roll out the new reverse registrar soon, that won’t be necessary any longer.

For those who were unable to attend the ecosystem call this week, below is a summary of the discussion along with a couple other thoughts.

Questions Asked

1. What is DM3 looking for?

The team has been heads down building out dm3 and the key ask is feedback on the project. @hai-ko.eth has been very receptive to feedback and I encourage everyone to continue to provide their perspectives.

2. Will adoption be hampered by the current design?

As of August 2022, there are ~200 million addresses[1] with some activity. ENS has ~400 thousand primary owners. Though the protocol outlined above can handle wallet-to-wallet communication for non-ens address it depends on an alternative delivery services. A concern is the splitting and siloing of the data as result of multiple delivery services.

To this point, @vegayp (part of the project) stated

“It is not for everyone, it is for people who are looking for something very specific” - Eduardo

Overall, I’m fan of having more messaging protocols. We need many experiments to figure out which one is right for web3. Hopefully, the multiple protocols will work with one another to avoid the data siloing issues of web2.

For transparency sake, nfty chat (I’m a co-founder) is building a protocol to handle many-to-many wallet communication, with wallet to wallet being a subset.

For those who want to explore protocols related to messaging in one form or another here are a few to follow:

  1. xmtp - wallet to wallet messaging
  2. farcaster - social network [2]
  3. epns - notifications
  4. waku - a suite of privacy-preserving, peer-to-peer messaging protocols

[1] Ethereum Cumulative Unique Addresses.
[2] Sufficient Decentralization for Social Networks - Varun Srinivasan

I would love to see and others adopt the standard DM3 have pioneered. A federated system with a standardised API seems the only way to build this in a decentralised fashion.


Thanks a lot for all the feedback. We’ll now work on a more formalized protocol specification draft where we take the feedback into account. As soon as the draft is finished (next 1-2 weeks), I’ll post it here for the second round of feedback.


I agree that a standard API is key.

The team at nfty chat is about to chat with the folks over at dm3, I can only see this as a positive for the ecosystem.


Thanks! We are looking forward to that! :smiley:


Good to see this initiative and at WalletConnect we demo’d our Chat API in July which offered exactly these features with native SDKs for Web (Javascript), Android (Kotlin) and iOS (Swift).

We have a couple of opinions on the design of dm3 but I would emphasize the following:

  • Key Derivation (we are using x25519)
  • Payload Encryption (we are using chacha20-poly1305)
  • Invite System (we allow anyone to invite a peer but requires consent for future messages)
  • Relay Transport (we build everything on of our pub-sub network)

There is definitely more components to consider such as:

  • Message Storage
  • History Recovery
  • Media Embedding

But the first 4 topics would be the most important ones IMO to find standardization


@pedrouid, thanks for your feedback! If I understood correctly, you are using chacha20-poly1305 for encryption/decrypting and ed25519 for authenticating the client. Are you using the same public key for both algorithms?

1 Like

Hey all, just want to start by saying I really enjoyed @hai-ko.eth’s initial post, and all of the thoughtful responses since. As @hai-ko.eth called out, ENS is an ideal home for decentralized public records relating to identity, especially those that might be related to communication.

Note: for context, I’m a co-founder of XMTP Labs, and along with our team, have been deep in the weeds in building a secure web3 messaging protocol called XMTP, so this subject is of incredible relevance and importance to me.

This exchange, especially in @slobo.eth, @nick.eth, and @pedrouid’s responses, really got me curious about identifying a neutral and service-agnostic approach for web3 messaging which could use ENS, and perhaps see formal adoption later. And with the 8/29 Weekly Ecosystem Meeting, it seems the community would appreciate an approach like this as well.

Attendees express concern that the DAO should be careful to consider any one protocol to pursue this work; ENS should focus on being involved with projects that have maximum applicability to users.

I thought I’d contribute to the discussion here by perhaps taking us down the path of a more agnostic approach to bringing messaging to ENS. It’s not entirely related to this particular topic, so I’ve broken out my idea for an ENS Messaging Provider (MP) record into its own topic. It would be awesome if those interested in the topic of web3 messaging could provide some feedback so that we can keep this conversation going: