如何使用web3.js退出MetaMask账户

21

我正在使用MetaMask向我的DApp合约发送交易。当用户点击注销按钮时,我需要帮助解决如何断开MetaMask账户与我的DApp的链接

前端:ReactJS

后端:Web3js,Solidity(以太坊)

6个回答

14

一旦一个钱包连接成功,用户需要自行断开连接,你对MetaMask没有控制权。实际上,通过检查是否可以访问他们的账户来模拟登录和退出的概念。

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");
}

我做的一件事是注意任何账户变化:

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

通常在我的应用程序中,我有一个初始化函数来检查Metamask是否安装?是否已连接?然后我存储状态,以便应用程序可以持久存在,即使在页面刷新时用户似乎已经登录。如果发生任何事情,例如帐户更改或断开连接,则会运行上述脚本并再次运行初始化脚本以重置状态。

// Runs on page load
initialise();

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

所以,就我所知,目前没有办法联系用户并断开连接,这并没有真正回答你的问题。

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();
});

然后我让我的UI对installedconnected变量做出反应。


2
这是正确的答案,因为目前没有API可以询问Metamask解除连接的帐户。 - Pat Niemeyer

3

有一个不错的框架https://usedapp.io/,可用于在TypeScript中设置前端与智能合约的交互。您只需使用其提供程序包装顶级组件即可:

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

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

接下来编写一个Header组件:

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> );};

请注意,这不会锁定 Metamask,它只是将您的应用程序与该帐户断开连接。


3
用户可以使用MetaMask内部的帐户断开按钮断开MetaMask帐户。此外,任何页面的刷新或重新加载都会自动断开MetaMask。

1
是的,我知道。但我想在我的前端实现一个按钮。当用户点击该按钮时,它应该注销到MetaMask。有关参考,请参见PanCakeSwap注销功能(https://exchange.pancakeswap.finance/#/swap)。 - Umair Janjua
1
他们实际上并没有断开Metamask的连接。即使在单击注销后,您仍然可以在Metamask中看到它显示“已连接”。他们可能只是分配了地址的变量。 - Dushyanth Kumar Reddy
3
这是正确答案。由于安全和隐私问题,连接/断开功能完全由用户掌控。通过编程方式重置账户数组并不会断开钱包的连接。 - q9f

2

我不知道你是否还存在这个问题,但在async函数内部,你可以调用clearCachedProvider。web3Modal变量被转换为我的web3实例化,例如const web3Modal = new Web3Modal...

await web3Modal.clearCachedProvider()

你好。这个程序可以工作,但是它并没有真正地将Metamask与网站断开连接。并且它向我显示了一个错误:未捕获的(在promise中)TypeError:ethereum.clearCachedProvider不是一个函数。就我个人而言,我更喜欢重置以清空账户数组。但是这也无法在Metamask扩展程序中断开连接... - Jo Le Belge
1
OP从未表示他们正在使用Web3Modal,此函数仅清除Web3Modal中选择的提供程序的缓存,因此与此无关。 - Andrew Katsewich

0

以上问题可以通过使用wagmi来解决。您只需要将disconnect与其他所需的软件包一起导入到您的项目中即可。

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
根据EIP-1193,web3.js目前仅支持连接和事件方面的操作,如断开连接事件、网络变化以及钱包账户变化。

eip-1193 的核心内容是,你只能通过 web3 编程方式建立钱包连接,并检测钱包用户端的事件变化,例如更改网络、更换钱包,但你不能在 web3 上编程方式断开钱包。在 pancake 使用 metamask 连接钱包的情况下,它只使用保存用户钱包地址的变量,当用户点击断开菜单时,它只删除 pancake 创建的变量内容,实际上并没有断开用户的钱包连接。 - Geraldine Adi Rachmattullah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接