设法在我的网站上连接到 Metamask,但我无法显示余额

Managed to connect with Metamask in my website but I can't show the balance

我使用以下代码通过我的应用程序成功连接到 MetaMask:

import React, { useEffect, useState } from "react";
import Web3 from "web3";
import styles from "./MetamaskAuthStyle.css";

function isMobileDevice() {
  return "ontouchstart" in window || "onmsgesturechange" in window;
}

async function connect(onConnected) {
  if (!window.ethereum) {
    alert("Get MetaMask!");
    return;
  }

  const accounts = await window.ethereum.request({
    method: "eth_requestAccounts",
  });

  onConnected(accounts[0]);
}

async function checkIfWalletIsConnected(onConnected) {
  if (window.ethereum) {
    const accounts = await window.ethereum.request({
      method: "eth_accounts",
    });

    if (accounts.length > 0) {
      const account = accounts[0];
      onConnected(account);
      return;
    }

    if (isMobileDevice()) {
      await connect(onConnected);
    }
  }
}

// async function getBalance(userAddress) {
//   console.log(web3.eth.getBalance(userAddress));
//   return web3.eth.getBalance(userAddress);
// }

export default function MetaMaskAuth({ onAddressChanged }) {
  const [userAddress, setUserAddress] = useState("");
  let web3: Web3 = new Web3();

  useEffect(() => {
    checkIfWalletIsConnected(setUserAddress);
  }, []);

  useEffect(() => {
    console.log(web3.eth.getBalance(userAddress));
    onAddressChanged(userAddress);
  }, [userAddress]);

  return userAddress ? (
    <div>
      Connected with <Address userAddress={userAddress} />
      <p>Balance: </p>
    </div>
  ) : (
    <Connect setUserAddress={setUserAddress} />
  );
}

function Connect({ setUserAddress }) {
  if (isMobileDevice()) {
    const dappUrl = "metamask-auth.ilamanov.repl.co"; // TODO enter your dapp URL. For example: https://uniswap.exchange. (don't enter the "https://")
    const metamaskAppDeepLink = "https://metamask.app.link/dapp/" + dappUrl;
    return (
      <a href={metamaskAppDeepLink}>
        <button className={styles.button}>Connect to MetaMask</button>
      </a>
    );
  }

  return (
    <button className={styles.button} onClick={() => connect(setUserAddress)}>
      Connect to MetaMask
    </button>
  );
}

function Address({ userAddress }) {
  return (
    <span className={styles.address}>
      {userAddress.substring(0, 5)}…
      {userAddress.substring(userAddress.length - 4)}
    </span>
  );
}

我是这个领域的新手,我想了解如何显示已登录用户的余额并显示断开连接按钮,以便用户可以注销。我已经尝试制作 getBalance 函数,但出现以下错误:

Error: Provided address is invalid, the capitalization checksum test failed, or it's an indirect IBAN address which can't be converted

将默认的 dappUrl 更新为您的项目 URL:

const dappUrl = "metamask-auth.ilamanov.repl.co"

这里是关于如何通过 Web3.js 将 React 应用程序连接到 Metamask 的方法。 主要思想是使用 React 钩子来环绕预期的 web3.js 函数。 下图均显示 (1) 如何获取当前账户的余额和 (2) 任意指定账户的余额。

首先让我们在一个单独的文件中创建一个自定义 React 钩子 useWeb3.js 并将所有 Metamask/web3 连接逻辑放在那里。这个钩子如下:

import { useState } from 'react';
import Web3 from 'web3';

function useWeb3(setIsLoading, setErrorMessage) {
  // web3 instance
  const [provider, setProvider] = useState(null);
  // active account
  const [account, setAccount] = useState('');
  // connect this function to a button click event
  const connect = async () => {
    try {
      setIsLoading(true);
      setErrorMessage('');
      // ensure Metamask is installed
      if (!window.ethereum) throw new Error('You should enable Metamask');
      // show Metamask prompt
      await window.ethereum.request({ method: 'eth_requestAccounts' });
      // connect Metamask to web3.js and get a web3 provider instance
      const web3 = new Web3(window.ethereum);
      setProvider(web3);
      // refresh account on change
      window.ethereum.on('accountsChanged', (accounts) =>
        setAccount(accounts[0]),
      );
      // retrieve Metamask accounts from web3
      const accounts = await web3.eth.getAccounts();
      setAccount(accounts[0]);
    } catch (error) {
      setErrorMessage(error.message);
    } finally {
      setIsLoading(false);
    }
  };
  // connect this function to a disconnect button
  const disconnect = () => {
    setProvider(null);
    setAccount('');
  };
  return { connect, disconnect, provider, account };
}

export default useWeb3;

请注意,将 metamask/web3 连接代码移动到它自己的自定义挂钩中很方便, 以便在应用的多个组件或部分中重复使用。

要动态观察余额信息,我们可以创建一个useBalance()钩子。这是一个使用上述 useWeb3() 钩子的示例实现:

import { useEffect, useState } from 'react';

function useBalance(web3, account, setLoading, setErrorMessage) {
  const [balance, setBalance] = useState('?');
  useEffect(() => {
    if (web3 && account) {
      (async () => {
        try {
          setLoading(true);
          setErrorMessage('');
          // Will convert an upper or lowercase Ethereum address to a checksum address.
          // https://web3js.readthedocs.io/en/v1.2.11/web3-utils.html#tochecksumaddress
          const correctedAccount = web3.utils.toChecksumAddress(account);
          const balanceInWei = await web3.eth.getBalance(correctedAccount);
          setBalance(
            // convert balance from wei to ether
            Number(web3.utils.fromWei(balanceInWei, 'ether')).toFixed(2),
          );
        } catch (error) {
          setErrorMessage(error.message);
          setBalance('?');
        } finally {
          setLoading(false);
        }
      })();
    }
  }, [web3, account, setLoading, setErrorMessage]);
  return balance;
}

export default useBalance;

然后我们可以连接到真实的区块链,看看是否一切正常。 要向 RSK 网络添加连接, 按照 here.

中的描述使用 Metamask 中的配置

现在 App.js 我们可以将所有挂钩放在一起来检索余额。

奖金示例

这是另一个包含 用户可以粘贴的文本字段 来自 RSK explorer 的任何地址 并查看其余额。 它还利用了上面的 useWeb3() 钩子。

import { useState } from 'react';
import useWeb3 from './hooks/useWeb3';
import useBalance from './hooks/useBalance';
import './App.css';

function App() {
  // loading status
  const [isLoading, setIsLoading] = useState(false);
  // error messages
  const [errorMessage, setErrorMessage] = useState('');
  // get active account and balance data from useWeb3 hook
  const {
    connect,
    disconnect,
    provider,
    account: activeAccount,
  } = useWeb3(setIsLoading, setErrorMessage);
  // get active account balance from useBalance hook
  const activeBalance = useBalance(
    provider,
    activeAccount,
    setIsLoading,
    setErrorMessage,
  );

  // random non-empty account from RSK explorer https://explorer.rsk.co/
  const [customAcount, setCustomAccount] = useState(
    '0xC2a41f76CaCFa933c3496977f2160944EF8c2de3',
  );
  // get balance of the custom account
  const customBalance = useBalance(
    provider,
    customAcount,
    setIsLoading,
    setErrorMessage,
  );

  return (
    <div className="App">
      {/* instantiate web3 only after a user clicks the button */}
      {/* avoid doing it automatically */}
      {!provider ? (
        <button onClick={connect}>Connect to MetaMask</button>
      ) : (
        <>
          <p>Connected with {activeAccount}</p>
          <p>My balance: {activeBalance} RBTC</p>

          {/* let a user enter any address and see its balance */}

          <p>Check RSK account:</p>
          <input
            type="text"
            value={customAcount}
            onChange={(e) => setCustomAccount(e.target.value)}
            style={{ width: '25rem' }}
          />
          <p>
            <a href={`https://explorer.rsk.co/address/${customAcount}`}>
              RSK account
            </a>
            {' balance:'}
            {customBalance} RBTC
          </p>
          <button onClick={disconnect}>Disconnect</button>
        </>
      )}
      {/* show loading and error statuses */}
      {isLoading && <p>Loading...</p>}
      {errorMessage && <p>{errorMessage}</p>}
    </div>
  );
}

export default App;

Connected with 0x1926617E081D3a670b3553FB0ba75180Bc01b215

My balance: 0.00 RBTC

Check RSK account:

0xC2a41f76CaCFa933c3496977f2160944EF8c2de3
RSK account balance:10.53 RBTC

[Disconnect]

如果您想尝试一个工作示例,请查看 demo-code-snippets/web3-react-show-balance.