Учебник: Подключение к MetaMask с помощью ванильного JavaScript

В этом посте вы узнаете, как просто подключить ваше фронтенд-приложение к кошельку MetaMask, используя простой код JavaScript.

Цель состоит в том, чтобы продемонстрировать, насколько это просто, без всякого шума библиотек типа React.

Давайте начнем.

Создаем новую песочницу Vanilla JavaScript Sandbox

Для начала откроем https://codesandbox.io/ и создадим новую песочницу для VanillaJS.

Вы можете удалить все содержимое файла index.js, чтобы начать все с чистого листа.

Теперь мы готовы к работе!

Понимание window.ethereum

Чтобы подключиться к кошельку MetaMask, нам необходимо программно проверить, установлено ли у пользователя расширение MetaMask в браузере. Для этого мы можем просто вставить этот код в наш файл index.js:

if (typeof window.ethereum !== "undefined") {
  console.log("MetaMask is installed!");
} else {
  console.log("MetaMask is NOT installed!");
}
Вход в полноэкранный режим Выйти из полноэкранного режима

После вставки проверьте вкладку Console в вашей песочнице, вы должны увидеть сообщение console.log. Если у вас не установлен MetaMask, убедитесь в этом, посетив официальный сайт и выбрав правильную версию для вашего браузера.

Продолжаем, что же такое window.ethereum вообще? Если не вдаваться в подробности, расширение браузера внедряет этот объект в ваш браузер. Этот объект ethereum более формально называется Ethereum Provider, который, как следует из названия, предоставляет вам API для доступа к сетям на основе Ethereum.

Если вам интересно узнать об API Ethereum Provider, читайте подробнее здесь.

Проверка наличия у браузера пользователя доступа к кошельку MetaMask

Теперь давайте создадим кнопку, которая будет сообщать нам, готовы ли мы подключиться к MetaMask или нет на основе того, доступен ли window.ethereum или нет.

<!-- index.html -->

<!DOCTYPE html>
<html>
  <head>
    <title>Parcel Sandbox</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <button id="connect-btn">Connect Wallet</button>

    <script src="src/index.js"></script>
  </body>
</html>
Вход в полноэкранный режим Выход из полноэкранного режима
// index.js

function isEthereumAvailable() {
  return window.ethereum !== "undefined"
}

const connectButton = document.getElementById('connect-btn')

function init() {
  if (isEthereumAvailable()) {
    connectButton.textContent = 'Connect Wallet'
    connectButton.removeAttribute('disabled')
  } else {
    connectButton.textContent = 'Ethereum not available. Please install MetaMask!'
    connectButton.setAttribute('disabled', true)
  }
}

init()
Вход в полноэкранный режим Выход из полноэкранного режима

Отлично, теперь у нас есть кнопка, которая будет отключена и скажет пользователю пойти и установить MetaMask в случае, если он недоступен. В противном случае будет отображаться «Подключить кошелек».

Отображение всплывающего окна MetaMask для запроса разрешений на просмотр учетных записей пользователей

Теперь, когда у нас есть кнопка, нам нужно убедиться, что при нажатии на нее у пользователя появится всплывающее окно MetaMask.

<!-- index.html -->

<!DOCTYPE html>
<html>
  <head>
    <title>Parcel Sandbox</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <button id="connect-btn">Connect Wallet</button>

        <-- Add this line so we can display the connected account -->
    <div id="account">Account not connected</div>

        <-- Add this line so we can display errors -->
        <div id="error"></div>

    <script src="src/index.js"></script>
  </body>
</html>
Вход в полноэкранный режим Выход из полноэкранного режима
function isEthereumAvailable() {
  return window.ethereum !== "undefined";
}

const connectButton = document.getElementById("connect-btn");

// + Add this two elements to give feedback to the user
const accountElement = document.getElementById("account");
const errorElement = document.getElementById("error");

// + Add this function to request the user accounts
//   This will display the MetaMask popup to the user
async function getAccounts() {
  return window.ethereum.request({
    method: "eth_requestAccounts"
  });
}

// + Add the connect function that will be triggered by the connectButton
function connect() {
  connectButton.textContent = "Loading...";
  errorElement.textContent = "";
  return getAccounts().then(showAccount).catch(showError);
}

// + Display the selected wallet address
function showAccount(accounts) {
  if (accounts.length > 0) {
    accountElement.textContent = 'Account: ' + accounts[0];
    connectButton.textContent = "Connected";
  }
}

// + Displays an error to the user when trying to connect the wallet
function showError(err) {
  connectButton.textContent = "Connect Wallet";
  errorElement.textContent = err.message;
}

function init() {
  if (isEthereumAvailable()) {
    connectButton.textContent = "Connect Wallet";
    connectButton.removeAttribute("disabled");

    // + Add this line to add the connect function to the button
    connectButton.addEventListener("click", connect);
  } else {
    connectButton.textContent = "Ethereum not available";
    connectButton.setAttribute("disabled", true);
  }
}

init();
Вход в полноэкранный режим Выход из полноэкранного режима

Обнаружение и отображение текущей сети

Давайте добавим новый элемент в наш index.html.

... same as before
<body>
  <button id="connect-btn">Connect Wallet</button>
  <div id="account">Account not connected</div>
  <div id="error"></div>

    <!-- Add this line so we can display the connected network --> 
    <div id="chain"></div>

    <script src="src/index.js"></script>
</body>
Вход в полноэкранный режим Выйти из полноэкранного режима

В наш файл index.js мы добавим пару новых функций:

... same as before
// Add this after errorElement variable
const chainElement = document.getElementById("chain");

async function getChainId() {
  const chainId = await window.ethereum.request({ method: "eth_chainId" });
  return chainId;
}

// We will use this to display a friendly name for the chain,
// as the getChainId method will give us the chainId.
function getChainName(chainId) {
  switch (chainId) {
    case "0x1":
      return "Ethereum Main Network";
    case "0x3":
      return "Ropsten Test Network";
    case "0x4":
      return "Rinkeby Test Network";
    case "0x5":
      return "Goerli Test Network";
    case "0x2a":
      return "Kovan Test Network";
    default:
      default: "Chain not supported"
  }
}

function showChain(chainId) {
  chainElement.textContent = getChainName(chainId);
}
Вход в полноэкранный режим Выход из полноэкранного режима

А в нашей функции connect обновим ее, чтобы она выглядела следующим образом:

function connect() {
  connectButton.textContent = "Loading...";
    chainElement.textContent = "";
  errorElement.textContent = "";
  return getAccounts()
    .then(showAccount)
    .then(getChainId)
    .then(showChain)
    .catch(showError);
}
Вход в полноэкранный режим Выход из полноэкранного режима

Вот и все, конечный результат должен выглядеть следующим образом:

Оцените статью
Procodings.ru
Добавить комментарий