1

我的 dApp 必须连接到 MetaMask。文档中有两个粗鲁的解决方案:让用户每次手动单击连接 btn 或在页面加载后弹出连接确认。我想实现唯一方便的解决方案:第一次用户通过单击连接 btn 并与 MetaMask 弹出窗口交互手动连接,然后我的 dApp 检测到该连接仍然建立并使用此连接。我找不到解决方案,但我在其他 dApp 中看到了这一点(例如Capture the ether),我使用:

import detectEthereumProvider from '@metamask/detect-provider';

const provider = await detectEthereumProvider(); 

if (provider) {
  connect(provider)
} else {
  // kind of "Install the MetaMask please!"
}

function connect(provider) {
  // How to check if the connection is here
  if (//connection established) {
    // Show the user connected account address
  } else {
    // Connect
    provider.request({ method: "eth_requestAccounts" })
      .then // some logic
  }
}
4

2 回答 2

1

我假设你已经在Ethereum Provider API上找到了 Metamask 文档。本节指定了使您的应用正常运行所需执行的三个步骤:

  • 检测以太坊提供者(window.ethereum)
  • 检测用户连接到哪个以太坊网络
  • 获取用户的以太坊账户

您的代码片段执行第一部分 - 它检测提供者。根据本节,要检测网络,您可以使用以下代码

const chainId = await ethereum.request({ method: 'eth_chainId' });
handleChainChanged(chainId);

ethereum.on('chainChanged', handleChainChanged);

function handleChainChanged(_chainId) {
  window.location.reload();
}

而最关键的部分 - 获取用户帐户。

let currentAccount = null; 

function handleAccountsChanged(accounts) {
  if (accounts.length === 0) {
    console.log('Please connect to MetaMask.');
  } else if (accounts[0] !== currentAccount) {
    currentAccount = accounts[0];
  }
}

document.getElementById('connectButton', connect);

function connect() {
  ethereum
    .request({ method: 'eth_requestAccounts' })
    .then(handleAccountsChanged)
    .catch((err) => {
      if (err.code === 4001) {
        console.log('Please connect to MetaMask.');
      } else {
        console.error(err);
      }
    });

用户第一次登录后,Metamask 下次不会弹出。

于 2022-02-20T11:06:46.357 回答
1

我终于找到了一个可能的解决方案,结果证明它应该很简单。以太坊 JSON-RPC 中有一个eth_accounts方法,它允许我们在不实际请求的情况下请求可用帐户。这样我们可以检查 metamask 是否仍然连接(如果有任何帐户),并避免自动请求或每次都需要手动单击“连接”。简单的示例实现可能是:

// detect provider using @metamask/detect-provider
detectEthereumProvider()
.then(provider => {
    if (provider && provider.isMetaMask) {
        provider.on('accountsChanged', handleAccountsChanged);
        //connect btn is initially disabled
        $('#connect-btn').addEventListener('click', connect);
        checkConnection();
    } else {
        console.log('Please install MetaMask!');
    }
})

function connect() {
    ethereum
        .request({ method: 'eth_requestAccounts'})
        .then(handleAccountsChanged)
        .catch((err) => {
            if (err.code === 4001) {
                console.log('Please connect to MetaMask.');
            } else {
                console.error(err);
            }
        });
}

function checkConnection() {
    ethereum
        .request({ method: 'eth_accounts' })
        .then(handleAccountsChanged)
        .catch(console.error);
}

function handleAccountsChanged(accounts) {
    console.log(accounts);

    if (accounts.length === 0) {
        $('#connection-status').innerText = "You're not connected to MetaMask";
        $('#connect-btn').disabled = false;
    } else if (accounts[0] !== currentAccount) {
        currentAccount = accounts[0];
        $('#connection-status').innerText = `Address: ${currentAccount}`;
        $('#connect-btn').disabled = true;
     }
}
于 2022-02-25T11:13:58.300 回答