ChainSafe / web3.unity

🕹 Unity SDK for building games that interact with blockchains.
GNU Lesser General Public License v3.0
920 stars 235 forks source link

Can't specify which MetaMask Account (public address) to sign the message #134

Closed eliasfeijo closed 2 years ago

eliasfeijo commented 2 years ago

I'm using ChainSafe to create a Login with MetaMask functionality for a Desktop game.

The problem is: the method Web3Wallet.Sign(message) always opens the user's first MetaMask Account (public address) registered. The user can't switch to another Account in the dialog, and I can't specify the Account in the Sign method. In my application, the user inputs their Account public address in an Input Field. If the user wants to sign the message with any other account that is not the first, he can't. The MetaMask Sign message dialog automatically picks the first account for signing the message, and the user can't choose another public address to sign the message.

Is there a way to specify which MetaMask Account that will sign the message?

I'm guessing that this is also an issue with the SendTransaction method, if I can't specify the from wallet then my game will have problems.

To Reproduce String signature = await Web3Wallet.Sign("My Message");

Expected behavior The user should be able to select which MetaMask Account he will use to sign the message. Or the application should be able to specify which public address, from the user's wallet, should be used to sign the message.

Screenshots The selected MetaMask Account was the second one, in the chrome extension, but the dialog always open with the first account and I can't change it. As you can see, the account name is grayed out, and I can't interact with it: MetaMaskLogin

As you can see below, MetaMask asks if it is the correct account, because the currently selected account (in the chrome extension) is different than the one being used to sign the message: MetaMaskLoginMessage

Desktop:

eliasfeijo commented 2 years ago

I've searched the internet for similar problems, and I've found this related post: https://forum.moralis.io/t/authenticate-with-metamask-always-use-the-first-account-and-not-the-selected-one/5409/18

I think the problem here is happening because I had already connected with my first account (Account 1) with the application, using ChainSafe. And after this first connection I can't connect any other accounts of my wallet, it always picks up the first account and it doesn't give me the option to switch.

Is this really is a bug on ChainSafe side, or am I missing something? I'm not very familiar with web3, so I don't know if it is possible for the application to select which one the MetaMask Accounts (matching the public address defined by the application) that will be used to sign the message.

In the future I will also need to specify the from account of the SendTransaction method, because I'm storing the user's public address in a database, and the transaction must be sent from the correct address. Is this achievable using the ChainSafe web3 library for Unity?

If it isn't possible, could you help me by sharing some ideas, and maybe a solution for this problem? Thanks in advance.

KBryan commented 2 years ago

See if using the WebGLSignOut Prefab helps. WebGLSignOut

eliasfeijo commented 2 years ago

@KBryan I'm having trouble building for WebGL platform, so I can't test this prefab right now (I'm on Linux, Ubuntu 20.04).

But I've checked the prefab, and it only has a Button that calls WebGLSignOut.OnSignOut(), and this script is just doing this:

public void OnSignOut()
{
    // Clear Account
    PlayerPrefs.SetString("Account", "0x0000000000000000000000000000000000000001");
    // go to login scene
    SceneManager.LoadScene(0);
}

It isn't invoking MetaMask (or the ChainSafe dApp) for signing out, and AFAIK, PlayerPrefs.SetString() just stores this public address in the "Account" key of the unity's storage (a file in the player's HD, essentially). So even though I'm able to copy this code and run on Desktop, instead of WebGL, it still is not a solution for me, unfortunately.

I might have to implement my own solution, instead of using this library, but it would be frustrating. I'm still hoping that this bug can easily be fixed by the maintainers.

eliasfeijo commented 2 years ago

@KBryan I've managed to disconnect my MetaMask wallet by manually acessing the URL https://chainsafe.github.io/game-web3wallet/ and clicking on "Disconnect" inside the chrome's MetaMask extension. I've found this URL inside Web3Wallet.cs script.

It should be possible to have an action that invokes the disconnect wallet panel (for example: ?action=disconnect query string in the URL, just like the other existing actions). If I could see the code behind the dApp, I'd gladly create a PR to fix this issue, but it seems that it is not open sourced yet.

Fow now, I can only hope for a maintainer to fix this issue for me. It would be even better if they could add the features that I've described here (eg. specify the wallet that connects to the game). But I don't know if those are possible using the current MetaMask API for dApps. I haven't explored this field myself, just yet.

And I might have to, really soon, as we want to publish the game in the near future. If you don't have plans for fixing this issue, please let me know! So that I can direct my working effort. Many thanks!

eliasfeijo commented 2 years ago

I've found that there is a way to disconnect an account using the MetaMask extension API: https://github.com/MetaMask/metamask-extension/issues/8990#issuecomment-980489771.

Since there was no response from the maintainers, I guess that fixing this issue is not in the project's roadmap right now. So I'll be working on my own dApp solution, and try to integrate it with Unity (probably by using this lib and just editing the dApp URL in the scripts).

KBryan commented 2 years ago

Thanks for posting this. Will add this to the backlog. There are many things we are working on and they are all important. If you would like to contribute to things you find useful. It's greatly appreciated.

eliasfeijo commented 2 years ago

Thanks, @KBryan! As I've commented previously, I'd gladly contribute if the dApp was open source (and I certainly would have forked the repo at this point). But, currently, I have specific use cases in my game that the library itself probably doesn't need to meet user expectations. So, I think I'm not really the best person to contribute right now. But if you need help with anything, PM me on discord, I'm @elf_qwerty in the ChainSafe server.

Here are some features that I'm planning to implement on my dApp, that currently don't exist in this library:

sneakzttv commented 2 years ago

in web3gl.jslib add image in weblogin.cs do this and assign it to a disconnect button image and that'l trigger an account swap in metamask and you can do what you need from there

eliasfeijo commented 2 years ago

in web3gl.jslib add image in weblogin.cs do this and assign it to a disconnect button image and that'l trigger an account swap in metamask and you can do what you need from there

This doesn't help me, as I'm building for desktop and not for WebGL platform.

I've just implemented my own dApp solution instead of using the one provided by this library, which was really easy to create. If anyone is wondering about it, it's really simple. Then I added the feature of disconnecting the current selected account (which is kind of tricky, I had to search through issues on MetaMask extension repository for a way to do it), and the other feature I mentioned, which is to allow a "from" address to be passed to the dApp, to be able to select which account should perform the transaction.