-
Notifications
You must be signed in to change notification settings - Fork 5k
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
Allow dapp to disconnect accounts #8990
Comments
There are probably other ways of handling the account mismatch scenarios that you're describing. Could you give us a concrete example that we could use to work on? |
Ok. The account mismatch scenario is not actually my issue, it was just an example. My actual issue is the second example. I have a "disconnect" button, which will log a user out, so they can log in again with a different wallet. My dapp is designed for using 1 wallet at a time, in order to simplify things. Megan has logged in using MetaMask account1. She now wants to use MetaMask account2. She clicks the Disconnect button, and returns to the login page. When she selects MetaMask, the dapp calls .enable() however she is not prompted to select a different account. She has no other option than to go into her MetaMask settings and manually disconnect the dapp. If I could call disconnect with the Ethereum provider API, this would allow Megan to go through the initial .enable() flow again, without needing to use the MetaMask settings. |
This is similar to Roman’s request, wanting a way to re-prompt the user for possibly different accounts. I believe you can get this result today by either using the wallet_requestAccounts method or wallet_requestPermissions for the eth_accounts permission. I will verify this in the morning, need to do dinner now. |
One thing you could do also is to just use disconnect to represent local app state, and if a user disconnects again and then connects again and selects MetaMask, use the existing permission to resume the user’s session with no prompt. If the user switches account, they will be prompted within MetaMask to connect if they want, and your app can refer to accounts[0] as their most recently selected account. |
She does have another option; switching accounts within MetaMask. The MetaMask UI has always been the sole method of switching between accounts. If a user wants to switch accounts on a dapp, they use the MetaMask account menu. If a dapp wants the user to switch accounts, they ask the user to switch accounts within MetaMask (using the account menu). This was true before v8 as well. Does that handle your scenario adequately? Or is there some other scenario that warrants this disconnect feature? |
This would be great. Thanks I'll try out your wallet_requestAccounts suggestion and see if that will suffice. Thanks @Gudahtt . I would really like the behavior to work the same for all wallet types (WalletConnect, WalletLink). So disconnect should actually feel like a disconnect, and it should do what the user expects. I don't think that just keeping it the way it has always been is a good argument. I know MetaMask is working hard to update UX after feedback, but I also think I should have the power to use it however I want to provide the best experience for my users. If I can provide a better experience in my dapp for the user, then I should be able to. Asking the user to interact with their metamask settings for something so simple is a bit of a backwards step. |
I didn't mean to suggest that allowing dapps to disconnect was a bad idea necessarily. I would just like to understand the motivation. I doubt we're likely to design any such method well without understanding the use cases well. I'm still having trouble understanding why a dapp would want to encourage a user to disconnect. The initial connection signifies that the user trusts the dapp enough to see their account(s), so I can see the user wanting to disconnect if they lost trust somehow. Or maybe the user doesn't intended to use the dapp anymore, and wants to disconnect to de-clutter their wallet permissions. But neither of those are of concern to a dapp. |
I'm not encouraging disconnection. I'm just trying to provide the simplest, easiest interface for managing multiple accounts. Logging in/out of the app is the most familiar "web2" method to achieve this. I like the KISS way of doing things. I could add a switching account feature like Google does, but I think that's overkill, and would unnecessarily complicate an otherwise straightforward app. It would require much more design and development cycles as well |
On a second look, it turns out the method you want is So: const permissions = await ethereum.request({
method: 'wallet_requestPermissions',
params: [{
eth_accounts: {},
}]
}); |
Trying now. will report back and close this issue if I am successful :) |
I tried both Neither will trigger the prompt again. UPDATE: Scratch that. |
Great success! Pasting code here for others. const walletAddress = await window.ethereum.request({
method: "eth_requestAccounts",
params: [
{
eth_accounts: {}
}
]
});
if (!isReturningUser) {
// Runs only they are brand new, or have hit the disconnect button
await window.ethereum.request({
method: "wallet_requestPermissions",
params: [
{
eth_accounts: {}
}
]
});
} |
In case it's useful, I landed here looking for a way to create a disconnect button. The use case is that some users might expect this, especially if connecting the wallet replaces an account login. Yes, many know that you can do this from the wallet itself, but it's not the common convention. |
@jaymutzafi yes, this is exactly what I was able to accomplish using this code #8990 (comment) You can try it yourself here https://spendless.io |
I am don't understand.... HOW U DO THAT, BRO ? |
i also still not get how to do that ?
this code makes disconnect happened ? |
This code is disconnecting from metamask only 1 profile if user have more then one of it... |
this code doesn't disconnect from metamask ? but gives a popup a confirm account list . did i something wrong ? |
please help, my code is just like your pasted here .But it works difference and open a confirm account popup as like login metamask does.
|
Yes, you are right! This code calls a popup from metamask. And if you are clicking on any profile to LOGIN - you are disconnecting first profile from website. I don't know how it works .... |
@pi0neerpat, i am unable logout/disconnect) from metamask in react.js, plz help me |
checked spendless.io and disconnect there works as supposed to, without showing metamask popup again, and somehow opensea also knows how to disconnect. has anybody cracked this? :) funny that issue is closed, like it was resolved, but it was not :) |
@ddon While I totally feel your pain, its not really an issue with MetaMask, but rather your implementation of it. You essentially have to keep track of some state (connected/no connected) in your app. I do this with local storage. If the user disconnects, then I call different functions the next time they hit the connect button. Check out the code I posted again and hopefully this will make it more clear. |
There is no need to call 'wallet_requestPermissions' before 'eth_requestAccounts' because the former is called under the hood for the 'eth_accounts' permission when calling the latter, check out the doc: document.getElementById('connectButton', connect);
function connect() {
ethereum
.request({ method: 'eth_requestAccounts' })
.then(handleAccountsChanged)
.catch((error) => {
if (error.code === 4001) {
// EIP-1193 userRejectedRequest error
console.log('Please connect to MetaMask.');
} else {
console.error(error);
}
});
} |
I have read the thread and didn't see any approach to actually disconnect metamask, as the dapp could always call
|
https://spendless.io doesn't disconnect account on disconnect button click. It just updates UI, but you can see your wallet is still connected inside Metamask extension. Also the code examples with requestPermissions and requestAccounts just open Metamask modal and allow only disconnect 2nd, 3rd, etc accounts, but one account will always connected. |
Who cares? There's no absolutely no reason to do this. It seems many people here are searching for a solution to a problem that doesn't actually exist. The purpose of this issue was to find a good UX experience to allow the user to connect a different account. We solved it. After disconnect, the next time they hit connect they can select a different account. This is the best possible experience. Anything beyond that is a waste of time. |
Hi @pi0neerpat I'm currently working on a dapp that requires both metamask and coinbase wallet support like you have on spendless.io. One thing that I have noticed is that if you switch accounts between coinbase/metamask on any subsequent connect it always picks up the coinbase wallet address even if you select Here's a video of the reproducing my findings on spendless.io: multiwallet.mov |
So is there a way to request Metamask disconnects itself from the website or not? Its not clear from reading the thread. I tested the Seems like a missing functionality. Why wouldn't a website want to offer a user a simple button to press when they want to disconnect their wallet from the site? "Power users know how to do it from inside the wallet" isn't a counterargument. It should be exposed to the website.
|
There is no such thing as a wallet "disconnect". Once a dapp knows the wallet address, they have this information forever. Unlike an OAuth2 connection, there is no way to "revoke/disconnect" access to the user's information, since this information is on-chain. "Disconnect" is just syntactic sugar to describe UX for "user intends to connect a different wallet". Crypto is about control. We must be aware of what information we are gathering from the user (IP address, cookies, wallet address, etc.), and be careful what we do with it. @romeldris thanks! Looks like a bug to me. |
I think that's not the point. The purpose here seems to be that we only need the same behaviour one gets from disconnecting from MetaMask, but we need to trigger it from a connected site. I've tried |
+1 |
Sorry for piling on this closed issue, but just want to add my two cents.
This is obviously 100% accurate, but in my experience, it's not how the average user understands the process of connecting — and that is ultimately the only thing that matters. Connecting & disconnecting feels so similar to logging in & out of a site via an oAuth flow (which everyone has done a million times by now) that I really doubt most people are aware of the nuance. Given that:
Why would a web2 site offer a logout button? Because the user has finished what they came for with that particular account, and now either want to end the session to force an explicit login the next time they visit for security reasons, or switch to a different account. In order to make my users (especially those not well-versed with web3) feel as at-home as possible, I would like to avoid the additional mental overhead of making them understand the nuance of connecting & disconnecting vs. what they're used to — logging in & out of a site. If I don't have a "disconnect" / "log-out" button on my site, I bet a good number of users would go searching for it, unaware that they need to disconnect from within their wallet app, because that's not what they used to with classic oAuth logins. Additionally, while of course I as the developer don't want to declare my own site as "untrustworthy", my users may not want to stay connected to my site, and prefer disconnecting. Why shouldn't I be able to make this convenient for them as a feature? Lastly, connecting a wallet is obviously NOT akin to authenticating, but if my app requires a signing challenge for a real log-in, the situation becomes even worse. Now, my user can log in to my site by connecting a wallet and then signing a message. And they can also log-out (in the classic web2 sense) by clicking "Log out". But after doing this, their wallet stays "connected" — which I'd bet is not at all what the average user would expect. After all, they just logged in by connecting their wallet and confirming a signature, so why would logging out not undo the connection too? |
@danfinlay I think there is a good reason for I as a user to want this disconnect functionality. I completely agree it makes no sense to use the UI to disconnect if you don't trust the UI. But if I connected, that means I DO trust the UI. What I don't trust is the UI 1 month from now, or 1 year for now. I have seen users use disconnect in the past thinking they were being prudent in this way. They were unaware that applications are simply just simulating a disconnect and that their wallet is still connected. To me this is a problem and we should instead be training the users to expect something resembling a confirmation that they are indeed disconnected from metamask. |
@vincenzor summed this up pretty well
@pi0neerpat can you reopen this? What does it take to get an an actual @MetaMask dev to reply.... |
I'm unable to disconnect from metamask. Tried all the examples people commented here but the program opens the metamask to connect instead of disconnecting. |
On the Metamask chrome extension, if you go to . . . -> Connected Sites -> (select your site) Disconnect, then it disconnects your wallet. |
This thread has been open for a while and I know I'm late to the game. But I'm running into an issue with web3-react and this connect/disconnect problem. It seems that if I connect MetaMask to my site and pick account A, then each time I come to the site and choose MetaMask as my preferred wallet, it always picks account A regardless of what's actually selected in MetaMask. There is no indication on the MetaMask UI that the current account is not connected and the site uses the previously-selected address to lookup balances, etc. This is a problem that needs to be addressed as it can lead to unexpected results for users and appears as "bugs" in the dApp when it's actually the wallet selection process. |
hey @mdcoon const onclickMetaMaskConnect = async () => {
setIsConnecting(true);
try {
const account = await requestWalletConnection();
if (account) {
await activate(injected, undefined, true);
}
} catch (error) {
console.error('Failed to connect MetaMask:', error);
}
setIsConnecting(false);
};
const requestWalletConnection = async () => {
try {
const permissions = await window.ethereum.request({
method: "wallet_requestPermissions",
params: [{ eth_accounts: {} }],
});
if (permissions) {
const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
return accounts[0];
} else {
console.error('Wallet connection permission denied.');
return null;
}
} catch (error) {
console.error('Error connecting to wallet:', error);
return null;
}
}; |
Connect |
You can try the following method to disconnect wallet => wallet_revokePermissions only available for the browser extension. https://docs.metamask.io/wallet/reference/wallet_revokepermissions/ metamask is successful, but other wallets may fail, you need to check before executing the function "wallet_revokePermissions" to avoid errors await window.ethereum.request({
"method": "wallet_revokePermissions",
"params": [
{
"eth_accounts": {}
}
]
}); |
I saw the MetaMask docs, it provice a method for disconnect to wallet. Let try this: await window.ethereum.request({
"method": "wallet_revokePermissions",
"params": [
{
"eth_accounts": {}
}
]
}); |
+1 |
Super happy that MIP-2 made it through 🙌 Thanks folks, that pretty much fixes this issue IMO. |
What problem are you trying to solve?
With the new updates to v8, it is important for the dapp developer to be able to disconnect an account. Otherwise, there is no way to handle account mismatch scenarios. Also without it, the user must manually disconnect their account in the MetaMask settings, which is a poor user experience.
Describe the solution you'd like
An Ethereum Provider API like
ethereum.disconnect()
orethereum.close()
Additional context
Related to #8956 . This would fall under the proposed Hard mode developer experience. This functionality is vital to being able to provide a streamlined experience for our dapp.
WalletConnect and WalletLink both implement this functionality.
The text was updated successfully, but these errors were encountered: