MSQ - MetaMask Snap Wallet and Authorization System

Hey everyone!
For the past couple of months we were working on a MetaMask Snap based wallet for the IC that is called Masquerade (MSQ for short).

In short MSQ is three things:

  • A crypto wallet, like MetaMask or NNS;
  • An authorization provider, like Internet Identity or Google;
  • A payment service, like PayPal.

Here is a demo-video covering the main features of MSQ:

Why?

  • II + NNS are super-secure, but some people find them hard to use.
  • Other browser-extension-based wallets are less secure, but easy to use.
  • So, it would be nice to have something in the middle.

Why Now?

  • MetaMask launched Snaps recently (now in Beta).
  • ckETH is coming to the IC soon.
  • MetaMask is 30M users, we can make their transition to the IC seamless.

What Are Snaps?

Snaps are extensions for MetaMask. They are distributed via NPM and everyone can develop one. They require only one-time installation, which can happen on any website, and then they used freely without limitations.

Snaps can securely derive deterministic randomness from user’s seed phrase. They can store information, make network requests and execute arbitrary logic. This logic can depend on a particular website that currently interacts with the Snap. For some websites a Snap can provide different functionalities than for others.

There is one downside though - they are very limited in their UI/UX capabilities.

What Is MSQ?

MSQ is a Snap and an accompanying IC-hosted Dapp. The Dapp is a continuation of the Snap which greatly extends its capabilities, mainly in terms of UI/UX. The Dapp is integrated with the Snap in a special way, so it has more control over the data inside, than any other website that interacts with MSQ.

MSQ offers similar levels of privacy and security as the Internet Identity, but with a much friendlier and snappier (haha) UX.

For more info about what MSQ can and how it looks, please refer to the demo video above.

Other websites integrate with MSQ by using a JS client library. The integration process is very simple. The library provides a special object to communicate with both: the Snap and the Dapp.
For example, there is a function that allows your users to authenticate themself. This function starts a user-side flow (which is covered in the video above), that as a result make your user authorized and returns you an Identity object, which you can pass in your HttpAgent or whatever agent you’re using and it will work as expected with the rest of your system.

Private keys (or any other privacy & security related information) never leave the Snap - they are always inside. Instead you have a number of functions to retrieve the information which is not considered private in the current context. For example, you can’t get all the identities that a particular user may use on your website (because a user might not want you to know them), but if a user is authorized within your website, then you can get a principal of an identity they are currently authorized with (as well as their pseudonym and an avatar they use on MSQ).

All the design decisions are made with a sole focus of giving users an absolute control of their privacy.

MSQ For Users

  • A simple way to dive into Internet Computer
  • Great UX
  • Great Privacy & Security

MSQ For Developers

  • Strategic move (30M users with almost no learning curve)
  • Easy to integrate
  • Powerful features

FAQ

Is it ready?
No, it’s not. We’re finishing the development process (2-4 more weeks) and communicating with the MetaMask team about including MSQ in the official list of approved Snaps (estimates are unkown).

Can I try it?
Yes, you can. The Dapp is available at msq.tech. You won’t be able to install the Snap with your regular MetaMask extension - you will need MetaMask Flask for this. Once you have it, the Dapp should prompt you with Snap’s installation process. Let me know if you have any problems with it.

What platforms are supported?
MSQ runs everywhere MetaMask Snaps can be executed. Currently it is Chrome Desktop and Firefox Desktop. There is no MetaMask on Safari. Mobile Snaps are coming, but there is no timeline for that.

I want to integrate it into my website. Are there any docs available?
There is no public documentation at the moment, but if you really want to, please DM me.

Is it open source?
Not yet, but once we’re in the list of official Snaps, it will be.

Why is it called Masquerade?
It is a methaphor. Any website, to which a user wants to interact with, is like a masquerade party. And before going to such a party a user might want to open their wardrobe and choose a mask, so nobody recognizes them.


Ask me anything in this forum thread. Thanks and take care!

16 Likes

Hi @senior.joinu

This is fantastic! I had trouble trying your dapp on Firefox though, it always failed with:

Uncaught (in promise) Error: [MSQ_METAMASK_ERROR]: Install MetaMask

(Yes, I had MetaMask installed)

Quick question: Did you look into the standards that the identity & wallet standards working group is working on?
In particular ICRC-25?

We would really appreciate you joining and sharing your experience with us!

2 Likes

Hi, @frederikrothenberger
Thanks a lot!

About your problem:

This bug, in particular.
Trying to fix it right now.

So, you can only access it via Chromium-based browsers at the moment.


Yes, I looked through these standards. I’m not ready to give an extensive feedback at the moment, but in short - they all assume that a signer component is also responsible for making canister calls, while this is not the case with MSQ. MSQ is just an Identity from the system’s point of view. So it might be difficult to implement them for us.

I would like to attend the next WG call to make a demo for you, answering any questions you have, and to discuss the ICRCs, if you don’t mind.

3 Likes

I would like to attend the next WG call to make a demo for you, answering any questions you have, and to discuss the ICRCs, if you don’t mind.

That’s great! We would love to have a live demo and ask some questions.

they all assume that a signer component is also responsible for making canister calls, while this is not the case with MSQ.

We used to have the standard also specify that the relying party (RP) needs to submit the canister call. However, this leads to the issue that the RP is put in the position where it can lie about the outcome of canister calls.

Imagine an RP that requests to transfer some ICP, it gets the signed canister call, submits it and it succeeds. The RP still has the option to show a bogus failure screen (i.e. lost network connection, please try again) in order to trick users to sign another transfer.

Now, that particular scenario could be alleviated by always showing the balance and the last few transactions in the MSQ UI. But this only works because the ledger balances are public. This does not work in the generalized case, where there might not even be a way to re-check the result of a past canister call (since not all state is public). And even if it were, the way to check is different for each call, so this also does not generalize well across generic canister calls.

What are your thoughts on the scenario above? And if I understand correctly, the main barrier is that the tooling isn’t there, right?
I.e. if the tooling for the flow as proposed by the standard had the same level of library support as the usage of an Identity has, the MSQ Snap could be changed to submit the canister calls itself, right?

1 Like

About the scenario.

I don’t see how having an ability to prove that a transfer call (or any other) was indeed performed may prevent people from being scammed like this. We’re transferring money not to just transfer them, but because we expect some outcome from this. For example, if I transfer ICPs to some DEX, I expect them to appear in my DEX balance. But this state transformation is entirely in control of the DEX itself. If they want to scam me, they will do it anyway saying something like “Ooops, something went wrong, we didn’t receive your money”. Despite the fact that I know for sure they did, because my wallet did the request. Even if it didn’t, I will anyway blame the DEX, not the wallet.

Moreover, for the average user, technical details and certificates may not hold much significance. I envision scenarios where even if a wallet provides a response like “We performed the request ourselves, and here is the certificate,” it may not alter user behavior. The absence of funds in both wallet and DEX balances would likely result in a negative reaction, regardless of the certificate’s presence. It seems that issues of this nature might be better addressed through publicity, reputation, and legal channels, drawing parallels between Web2 and Web3 scenarios.


There is a number of barriers for us to integrate ICRC-25 in MSQ.

First of all, as you’ve noticed, DX is in our top priorities. Alongside privacy, security and UX. We want developers to be able to integrate with MSQ as soon as it is ready, doing as little work on their side as possible. For that we had to encapsulate MSQ in one of the existing programming abstractions. There are only two: Identity inteface from @dfinity/identity and Agent interface from @dfinity/agent.

At first we tried to represent MSQ as an Agent. This could allow it to make (and verify) canister calls by itself. But it didn’t work. Snaps are executed inside SES, which is brand new and not stabilized yet. I don’t know what is the reason exactly, but it was unable to verify replicas response signature. So, because of that we switched to the only available option for us - to represent MSQ as an Identity interface.

After the switch, everything become so much simpler and I’m now in love with the architecture that we have.


Another thing, which is a question as I see it (and I can’t find the answer in the ICRC-25 spec docs), is: are identities stored inside the signer party scoped by the website or not. By “scoping” I mean, is there a way for website A to utilize user’s identities from website B.

In regular MetaMask (and the majority of wallets) the identities are not scoped. You have a list of addresses (key pairs) and this list is global - every website is able to get a signature made by any of them. This leads to problems, as you described, that one dapp may do something bad with user’s data on another dapp. I believe, that if you’re developing a wallet that works like this, then you HAVE to implement something similar to ICRC-25, so you can at least limit a malicious dapp from making a mess. And as I understand, ICRC-25 was developed exactly with this kind of wallets in mind.

What I don’t like about this, is that such a solution seem to transfer the responsibility for the possible mess from wallet developers to wallet users. Because now they have to manually (or semi-automatically) check the list of canisters that a website may interact with, using their key pairs, and decline the connection request if they see something sketchy. I can’t imagine an average user doing this easily.

In Internet Identity (and in MSQ) the identities are scoped. And this is a much better move, as I see it, because it prevents the mess, without transferring the responsibility. Now, a website A can’t utilize user’s identities from website B, because website A doesn’t know them and has no access to their signing power.

And for such a wallet, I don’t see how integrating ICRC-25 would provide a lot of value. Users don’t interact with canisters directly, they interact with them in a context of some website. A website is unable to make canister calls to canisters ourside its perimeter with scoped user’s identities, because these requests are meaningless for a remote canister - it never before encountered such an identity, so there is no state associated with it.

The only exception, which is specific to MSQ, is when there was an identity linking event. But this event happens only from an approval from both: the developer of a website and the user. This is similar in concept to icrc25_permissions_request, but it is a permission to use your scoped identities on another website. A permission to share the website context, basically. And it is handled properly in MSQ, with a very expressive prompt to a user like “all kinds of bad things can happen”.


The third thing is the one we could easily overcome and it is about some minor incompatibilities with the standard.

For example, the standard says that a session MUST be terminated after some time, while in MSQ it is a feature to be able to not log out. Because you can simply lock your MetaMask and nobody can use your device, until the correct password is entered.


I’m looking forward to participate in the WG and discuss any of these topics further.

3 Likes

The bug should be resolved. MSQ now works on FireFox as well.

2 Likes

Thanks for answering this. However, I do not quite agree with the conclusion that is all the same to the end user. While yes, the user can still be scammed and I agree that there is no technical solution to prevent all scams, it still changes the above scenario from

  • the tech is unreliable and I lost money

to

  • I interacted with a scammy website that stole my money

To me, these are very different outcomes especially with regards to accountability.


I’m looking forward to participate in the WG and discuss any of these topics further.

Yes, me too. I think there is quite a bit more to discuss and it would be great to align as well. The more interoperable components we have, the better for the ecosystem.
Thanks for pushing forward on that front! :slight_smile:

1 Like

Unfortunately I’m still getting the same error. What do I need to do?

I’m running MetaMask flask Version 11.5.0flask0 on Firefox 119.0.1 (64-bit).

On Chrome, the whole MetaMask setup works fine, but I end up on a blank black screen…?

Could you please try resetting the cache?
Shift + Ctrl + R depending on your OS.

Let me know if this does not work.

UPD:

Oh, and also, the link I left should forward you to msq.tech/cabinet/my-assets - there is no content at the root route (/) at the moment.

UPD1:

If you want to play with plushies here they are:
https://2vkb3-yaaaa-aaaak-afdsa-cai.icp0.io/ - original domain
https://3rhoj-baaaa-aaaak-afdua-cai.icp0.io/ - updated domain, so you could also test linking (to link original to updated, just click the logo on the original webpage)

1 Like

Could you please try resetting the cache?
Shift + Ctrl + R depending on your OS.

I did that on Firefox but it didn’t help.

Oh, and also, the link I left should forward you to msq.tech/cabinet/my-assets - there is no content at the root route (/) at the moment.

That solved the issue on Chrome, I typed the URL manually (great choice btw, easy to remember). I would put a redirect there :wink:

If you want to play with plushies here they are:
https://2vkb3-yaaaa-aaaak-afdsa-cai.icp0.io/ - original domain
https://3rhoj-baaaa-aaaak-afdua-cai.icp0.io/ - updated domain, so you could also test linking (to link original to updated, just click the logo on the original webpage)

I played around with it and it worked great! :smile: :+1:
Great demo, definitely something to look out for. Do you have a timeline on when you want to move out of Beta?

1 Like

Thanks :slight_smile:
This one was purchased with ckBTC.

Done. If you open msq.tech/ and it doesn’t redirect you, there is something wrong with the cache on your machine. If the issue persists let me know. Maybe there is something special with Firefox on MacOS.

Thank you very much for taking your time and testing this out for us.

Thanks!

I hope it happens as soon as we’re in the list of the allowed Snaps. But maybe we will extend this so we move out of Beta when Snaps in general move out of Beta.

1 Like

It is now possible to create payment links in MSQ.

For example, here is a link that will allow you to transfer any amount of tokens to my ICP account, via MSQ:

msq.tech/pay
?kind=t
&canister-id=ryjl3-tyaaa-aaaaa-aaaba-cai
&to-principal=rmapb-pzxbf-4fimd-h33qy-aydfx-wxne6-64kqi-f6nwz-cfzyq-wf7tb-bqe

Once you click on that, it will redirect you to a special UI on MSQ, that will guide you though the process. If everything is good, you will send me some tokens without typing anything manually (except for the amount).

These links have the following structure:
msq.tech/pay + a search query string with the following arguments:

  • canister-id: <principal-string> - token canister id
  • to-principal: <principal-string> - recepient’s ICRC-1 account principal
  • to-subaccount?: <hex-string> - hex-encoded recepient’s ICRC-1 subaccount
  • amount?: <num-string> - a raw (e8s) amount of tokens to transfer, if none - the user is expected to enter their own amount
  • memo?: <hex-string> - hex-encoded ICRC-1 memo
  • kind?: 't' | 'd' - a cosmetic marker that will either render the phrase “pending transfer request” or the phrase “pending donation request”

This feature usefull in a lot of real-world scenarios such as requesting your friend to transfer you some amount of funds or embedding a donation button somewhere on the internet. One can use our payment links to simplify these actions.

For example, you can wrap such a link around an image, to create buttons which can be embedded anywhere, like this:

[Donate with MSQ]

If you click on that, it will redirect you to MSQ, automatically inserting my account id as your target. Try it.

You can create such a link for your own account via MSQ’s Receive UI:

Also, since under the hood this is just regular ICRC-1, you can use these links to make people transfer you money to other wallets via MSQ. For example, you can look up your principal ID in the NNS UI (top right corner icon button) and replace the to-principal payment link argument with this ID. Anyone who will use this link to transfer tokens will actually transfer them to your NNS wallet.

Try it out now at msq.tech
Take care.

6 Likes

Hello, everyone!

I’m thrilled to share some exciting updates with you:

  1. Currently, MSQ is undergoing a security audit conducted by Consensys Diligence, thanks to the MetaMask DAO, which generously provided a grant to support this effort.
  2. I recently received great news from Dfinity, who has also agreed to support our future endeavors with a significant grant.
  3. During this period, our focus has primarily been on fixing bugs, refactoring, and preparing for the audit. However, we have managed to introduce several new features:
    • You can now review your transaction history for each account, with support for both incoming and outgoing transfers.
    • MSQ now supports additional ICRC-1 tokens - the complete list of pre-whitelisted tokens includes all SNS tokens, ckETH, ckBTC, ICP, and OGY.
    • Token logos are now beautifully rendered.
    • You have the option to hide tokens with zero balances.
    • MSQ’s OpenGraph integration has been enhanced, ensuring that links shared on forums are visually appealing.

Additionally, we’ve launched an attractive landing page.

All preparations are in place for the upcoming Beta Release, expected in the first few weeks of April.

Wishing you all a wonderful day and my deepest thanks!

2 Likes