21

I am using MetaMask for sending transactions to contract in my DApp. I need help in How to Disconnect MetaMask account from my DApp when the user clicks on logout button.

Front-end: ReactJS

Back-end: Web3js, Solidity (Ethereum)

TylerH
  • 20,799
  • 66
  • 75
  • 101
Umair Janjua
  • 324
  • 1
  • 2
  • 11

6 Answers6

14

Once a wallet is connected it's up to the user to disconnect, you have no control over metamask. You essentially simulate the concept of logging in and logging out by checking if you can get access to their accounts.

const {ethereum} = window;
const accounts = await ethereum.request({method: 'eth_accounts'});
if (accounts && accounts.length > 0) {
    console.log("user is connected");
} else {
    console.log("user not connected");
}

One thing I do is to watch for any account changes:

window.ethereum.on('accountsChanged', async () => {
    // Do something
});

Typically in my app I have an initialise function that checks for metamask, is it installed? is it connected? then I store the state so the app can persist as though the user is logged in even on page refresh. If anything happens such as account change or disconnect the above script runs and I run my initialise script again to reset the state.

// Runs on page load
initialise();

// Runs whenever the user changes account state
window.ethereum.on('accountsChanged', async () => {
    initialise();
});

So, doesn't really answer your question, as far as I know there is now way to reach out and disconnect the user.

let connected = false;
let installed = false;

function isMetaMaskInstalled() {
    return Boolean(window.ethereum && window.ethereum.isMetaMask);
}

async function isMetaMaskConnected() {
    const {ethereum} = window;
    const accounts = await ethereum.request({method: 'eth_accounts'});
    return accounts && accounts.length > 0;
}

async function initialise() {
    connected = await isMetaMaskConnected();
    installed = isMetaMaskInstalled();
}

initialise();

window.ethereum.on('accountsChanged', async () => {
    initialise();
});

I then have my UI reactive to the installed and connected variables.

Ari
  • 5,301
  • 8
  • 46
  • 120
  • 2
    This is the correct answer in that there is currently no api to ask metamask to dissociate an account that is connected. – Pat Niemeyer Apr 04 '22 at 14:50
3

The user can disconnect MetaMask account using the account disconnect button within the MetaMask itself. Also any page refresh or reload automatically disconnects MetaMask.

Mikko Ohtamaa
  • 82,057
  • 50
  • 264
  • 435
  • 1
    yeah, I know that. But I want to implement a button on my front-end. when the user clicks on that button. It should Logout to MetaMask. For reference, see [PanCakeSwap](https://exchange.pancakeswap.finance/#/swap) logout functionality. – Umair Janjua Jun 07 '21 at 12:48
  • 1
    They are not actually disconnecting metamask. You can see that in metamask it still displays `connected` even after clicking logout. They may be just the variable which they have assgined the address – Dushyanth Kumar Reddy Jun 07 '21 at 15:45
  • 3
    This is the correct answer. The connect/disconnect functionality is entirely in the hands of the user due to security and privacy concerns. Resetting the accounts array programmatically does not disconnect the wallet. – q9f Sep 22 '21 at 07:46
3

There is a nice framework https://usedapp.io/ to set up frontend in typescript to interact with smart contracts. You basically wrap your top-level component with its Provider:

import { Mainnet,ChainId} from "@usedapp/core";

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <DAppProvider
      config={{
        supportedChains: [ChainId.Kovan, ChainId.Rinkeby],
      }}
    >
      <Component {...pageProps} />
    </DAppProvider>
  );
}

Then write a Header component:

import { useEthers } from "@usedapp/core";

export const Header = () => {
  
  const { account, activateBrowserWallet, deactivate } = useEthers();
  const isConnected = account !== undefined;
  return (
    <div >
      {isConnected ? (
        <Button  onClick={deactivate}>
          Disconnect
        </Button>
      ) : (
        <Button onClick={() => activateBrowserWallet()}>
          Connect
        </Button>
      )}
    </div> );};

Be aware that this is not going to lock metamask it will just disconnect your app from the account.

Yilmaz
  • 35,338
  • 10
  • 157
  • 202
2

I don't know if you still have the issue, but inside of an async function you can call clearCachedProvider. The web3Modal variable is cast to my instansiation of web3, e.g. const web3Modal = new Web3Modal...:

await web3Modal.clearCachedProvider()
Jamie
  • 1,004
  • 1
  • 14
  • 32
  • Hello. That's work but that's not really disconnect Metamsk from the site. And that's show me an error : Uncaught (in promise) TypeError: ethereum.clearCachedProvider is not a function Personnaly, I prefer reset to empty the account array. But that don't disconnect in metamask extension too... – Jo Le Belge Sep 03 '21 at 14:04
  • 1
    OP never stated that they were using Web3Modal, besides this function clears cache of chosen provider in Web3Modal, so it's not relevant at all. – Andrew Katsewich Jan 06 '22 at 14:08
0

The above problem can be solved by using wagmi.You jus need to import disconnect into your project along with other needed packages

import {
  useAccount,
  useConnect,
  useDisconnect,
  useNetwork,
  useSignMessage
} from "wagmi";

react:

const { disconnect } = useDisconnect();
const disconnectWallet = async () => {
    disconnect();
    refreshState();
  };
 <HStack>
          {!activeConnector ? (
            <Button onClick={connectWallet}>Connect Wallet</Button>
          ) : (
            <Button onClick={disconnectWallet}>Disconnect</Button>
          )}
 </HStack>
-1

as attached on EIP-1193, web3.js currently still working for connections and events only, such as disconnect events, network changes and wallet account changes only.

  • The essence of the contents of eip-1193 is, you can only make a wallet connection via web3 programmatically and detect changes in events on the wallet user's side such as changing networks, changing wallets, but you can't programmatically disconnect wallets on web3. In the case of pancake connecting wallet using metamask, it only uses the variable that holds the user's wallet address, when the user clicks on the disconnect menu it just deletes the contents of the variable created by pancake, and it doesn't actually disconnect the user's wallet. – Geraldine Adi Rachmattullah Aug 29 '21 at 11:30