MetaMask / metamask-snaps-beta

Fork of MetaMask that supports plugins! Read the Wiki!
https://github.com/MetaMask/metamask-snaps-beta/wiki
MIT License
142 stars 57 forks source link

Add API for message messaging/notification plugins #106

Open danfinlay opened 4 years ago

danfinlay commented 4 years ago

At last weekend's EthWaterloo hackathon, two of the winning entries extended MetaMask to incorporate messaging!

There is clearly a desire for a messaging/notification API, so I'm opening this issue as an initial catch-all for thoughts on the UI/API of this kind of feature.

For mere notifications, I think we can pretty easily canonize a new kind of EIP-2255 restrictedMethod that allows plugins the permission to show notifications. I think the bigger question is:

If a plugin wants to provide messaging/an inbox, where should it go? Should the assets list simply evolve into a general "toolbox", kindof a fancier type of bookmark list, or is there a more first-class place where people would prefer messaging in the wallet to exist?

If we did have a conversations tab, and this was populated by a plugin API, it would mean you could potentially have conversations from many protocols rolled into the same queue. That thought is pretty cool.

Anyways, share your thoughts, how should it work, what should it look like, etc.

jsdu commented 4 years ago

Hi! I am one of the hackers who worked on Connexion.

Wallets are the first place users would look if they were to have a new message pop up. It would be amazing if MetaMask had a tab called inbox. It would show a list of notifications and it would look very similar to the transactions view but styled accordingly. Handling messages would be determined by a standard that we should adhere to. There would be data within the message that would explain to the wallet exactly what should be displayed, whether it's an external link to an IPFS hosted website, or if it's just plain text.

Although it would be really cool to build everything within the plugin, some of the features that we would like to have would be too much for a plugin (sharing images, sending markdown). We're thinking of creating something similar to sending an email. I think the Wallet's role in communications should be to handle different protocols and broadcast them to the user based on certain settings that the user has set up. That way, third party applications can build upon this generic protocol and handle rich data if they so choose within their own application that the wallet redirects them to.

I am still thinking of what is the best course of action in terms of having a generic message.

  1. Should each message be sent as part of a transaction? (Maybe we can batch this up and send it through a relayer)
  2. Should each message be an event? Then Metamask will need to comb through and filter each event and each wallet will need to keep track of when a user has viewed the message, Should this be an api that companies handle that give to Metamask instead? We used Dfuse at the hackathon to handle this.
brantlymillegan commented 4 years ago

I wanted to just alert people if they didn't already know about another project trying to do something similar to this. Might want to include them in conversations? https://mailchain.xyz/

tboeckmann commented 4 years ago

Thanks @brantlymillegan - I saw Connexion and Wallet Notify liking their approaches a lot!

At Mailchain, we've created an offering for what we believe the standard for sending asynchronous messages using blockchain protocols should be. We built the Ethereum implementation initially and it works across testnets and mainnet.

Specification: https://github.com/mailchain/mailchain-specification

We welcome feedback from the community on better ways to handle/ extend message functionality... don't be shy to contribute ideas and feedback.

One extensible concept we created that may be handy is 'Programmable Envelopes' where the sender can specify how the message data is handled (i.e. message header and body stored off-chain vs on-chain, encrypted message for the recipient vs 'open letter' or anything else the community can dream up).

Storage type (and location) is intended to be flexible (any kind of object store e.g. S3, IPFS, etc.).

@jsdu

  1. Should each message be sent as part of a transaction? (Maybe we can batch this up and send it through a relayer)

There are strong arguments to support this approach. We implemented it this way so the transaction needed GAS (acting as anti-spam) and verification of sender/recipient was a little more transparent.

We'd like to explore batching as a way of reducing costs, but understand what tradeoffs there are.

  1. Should each message be an event?

Guaranteeing delivery is really important. While the trade off of waiting for the next block to show the tx may limit some applications (over near-instant events), supporting true decentralised asynchronous messages needs to leverage transactions in some way. Events may be useful to provide a temporary notification until the tx has been sufficiently confirmed.

@danfinlay: +1 for the conversations tab! There's a bunch of use cases listed on https://mailchain.xyz.

Without getting into the weeds of additional message features on Mailchain's roadmap, the most simple requirements that we'd see MetaMask need to consider are:

  1. Messages may contain a payment.
  2. Messages should be checked for validity (sender, file integrity etc) to prevent spam.
  3. The Ethereum account private key is needed for decryption if the account public key is used (related to metamask-extension/issues/1190).
  4. A user should be able to reply to a message (and that message be decrypted, then sent in a tx).

Happy to work together and help explore this further... let me know all your thoughts.

jsdu commented 4 years ago

@tboeckmann For my question of whether to use events, I was talking about Solidity events. I was thinking how would encrypted data be shared to another user, whether it is with a function call to store the message in state, to use Solidity events, or to simply attach it to the data field of a transaction.

I think layer 1 messaging would be detrimental in terms of user experience as each tx requires gas. This would be more geared towards notifying users. And to be fair, I don't think gas for a transaction would work as a spam filter, I think it would hinder regular users more. There could be services that would send transactions on behalf of users (gas station network, etc) as well.

Also happy to help and talk more about this, hope we can collaborate! I think decentralized messaging on blockchain would be really powerful.

danfinlay commented 4 years ago

For the purpose of keeping this MetaMask support productive, I'd recommend keeping it agnostic to the exact messaging protocol: Snaps have access to the blockchain, and can request access to the network, so there are a lot of approaches possible, and we'd love to implement an agnostic and extensible approach to these.

For MetaMask to best support these various approaches, the biggest questions for us are things like "Where do these messages best integrate into our interface?" and "What permissions does a messaging system require to work well?".

Sounds like the conversations tab is appealing, we will review this thread and keep talking with you as we start designing for this use case.

haardikk21 commented 4 years ago

Where do these messages best integrate into our interface?

I see two main approaches. Depending on whether this should be part of native MetaMask or remain a plugin. Natively: A conversations/messages tab would be the best way. Could extend the side menu to include more options than the assets manager. Plugin: There was talk at ETHWaterloo of allowing plugins to render their own HTML+CSS within Metamask. That could be utilised if this were to be added as a plugin.

What permissions does a messaging system require to work well?

Is this in the context of plugin permissions? If so, then 1) view list of eth addresses in metamask 2) alert/notify

I think permissions aren't as complex as some API requirements are. At the hackathon, some things were not working as expected which would've proven to be useful.

1) an event or callback when wallet is logged into or account is switched 2) a way to prompt metamask or automatically decrypt data using the account's private key 3) (if the message listener will be part of metamask) - a way to read those messages

robdefeo commented 4 years ago

@danfinlay Its exciting to see your plans to build a permissionless extension. This would allow Mailchain and other messaging applications to using Metamask as a key building block. I read your Introducing Web3 Plugins article and have looked through snaps API wiki.

My thoughts below are based on a first look at that and knowledge of building messaging applications. The trust that Metamask has built with users around key management offers messaging platforms a secure but trustworthy way to work with private keys.

Since each messaging protocol will likely have a different messaging standard especially early on, exposing a set of functions that would support messaging primitives would allow products to innovate ontop of Metamask and Snaps. We have outlined the Send, Receive, Read primitives plus the specification this can be useful to understand our approach. I believe exposing these primitives allows the community to build now and in the future.

To implement in the interface itself is more subjective, I think a lot depends on how much messaging UX you want in the extension. It gets a bit more complex as email vs instant messaging has a different UX. An initial approach could be to identify messages as belong to a messaging platform via a function (for mailchain its a prefix in the data field) then this could either display the message or deep link to the messaging platform.

Open to thoughts and feedback on this from the community. Big :+1: on the work Connexion and Wallet Notify have done at eth waterloo.

danfinlay commented 4 years ago

Thanks for all the ideas, these are great, please do keep them coming!

A note to messaging protocols that are hoping to use on-chain data to send messages to MetaMask users, and receive them using a snap:

Today, MetaMask achieves pretty good performance (network, cpu, and energy) by "sleeping" when not active. This is because we are very much not a full client, or even a light client at the moment, and so we don't keep up with blocks when the user is not actively engaged on the blockchain, instead allowing the user to connect to a full node of their preference, either local or remote.

If your protocol requires parsing every incoming transaction on the block that it is included, either:

I'm highlighting this because it's the kind of stuff we think about a lot as wallet developers, and if you're building a snap, this may be your first taste of wallet development, so I want you to know that not all users want to run a full client and keep it synced, so you will want your snaps to perform well under a variety of user preferences.