Подключение к различным кошелькам web3 с помощью Wagmi.sh и ReactJS

Привет всем! В этом посте я покажу вам, как подключаться к различным кошелькам web3 с помощью Wagmi.sh. В ходе этого руководства мы напишем базовый смарт-контракт с помощью Solidity, создадим и развернем проект с помощью Hardhat, будем взаимодействовать с ним с помощью EthersJS поверх React, развернем фронтенд на GhPages и скроем наши конфиденциальные данные с помощью переменных env.

Итак, для начала позвольте мне рассказать вам о том, что такое Wagmi.sh, для чего мы будем его использовать и зачем он нам вообще нужен?

Введение в Wagmi.sh и проект, который мы будем создавать

Согласно их сайту (https://wagmi.sh/) «wagmi — это коллекция крючков React, содержащих все необходимое для начала работы с Ethereum». Изначально меня заинтересовало то, что с помощью wagmi мы можем легко подключаться к различным провайдерам кошельков web3. Хотя есть и другие библиотеки, которые делают то же самое, я обнаружил, что wagmi очень проста в использовании. У них также есть страница сравнения библиотек, где они описывают их плюсы и минусы (https://wagmi.sh/docs/comparison). Самым большим плюсом для меня стало то, что использовать wagmi с Ethers.js — проще простого. Wagmi поддерживает следующие провайдеры кошельков: Metamask, Coinbase Wallet, WalletConnect и Injected.

Итак, наш проект будет довольно простым. Когда приложение откроется в первый раз, нам будут представлены различные кнопки, обозначающие соответствующих провайдеров кошельков. Мы можем выбрать любого из них для подключения к приложению. Вот первый экран, который мы видим.

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

В любой момент мы можем отключиться от выбранного провайдера кошелька и подключиться к другому.

Для этого приложения мы будем использовать тестовую сеть Goerli.

Часть первая: Создание бэкенда

Написание и развертывание смарт-контракта с помощью Hardhat

Давайте начнем наше приложение с создания пустого проекта Hardhat. Мы будем использовать Hardhat для развертывания нашего смарт-контракта в тестовой сети Goerli. Для написания смарт-контракта мы будем использовать язык solidity.

Для начала создадим пустую папку. В этой папке мы будем хранить как наш смарт-контракт, так и фронтенд для удобства использования. Поскольку я использую Linux, я создам папку wagmi-project, набрав в терминале mkdir wagmi-project. Я cd в папку и выполню следующую команду в терминале, чтобы создать файл package.json: yarn init -y (если вы используете npm, то вместо этого введите npm init -y). После этого я установлю hardhat, введя в терминале yarn add --dev hardhat. Затем я начну новый проект hardhat, введя npx hardhat в терминале и выбрав создать новый проект Javascript. Затем я добавлю некоторые зависимости с помощью yarn add --dev @nomiclabs/hardhat-waffle@^2.0.0 ethereum-waffle@^3.0.0 chai@^4.2.0 @nomiclabs/hardhat-ethers@^2.0.0 ethers@^5.0.0. Вот и все для установки хардхата. Теперь я просто удалю папки внутри папок contracts, scripts и test, которые мы только что создали.

Затем я введу yarn add dotenv, поскольку позже я буду использовать переменные окружения для защиты конфиденциальных данных, таких как закрытый ключ моего кошелька.

После того как все это сделано, я перехожу к файлу hardhat.config.js и изменяю его содержимое на следующее:

require("@nomiclabs/hardhat-waffle");
require("dotenv").config();

module.exports = {
  solidity: "0.8.0",
  networks: {
    goerli: {
      url: `${process.env.ALCHEMY_GOERLI_URL}`,
      accounts: [`${process.env.MY_PRIVATE_KEY}`],
    },
  },
};

Войти в полноэкранный режим Выйти из полноэкранного режима

Как вы можете видеть, здесь происходит несколько вещей. Помимо требования waffle от hardhat и библиотеки dotenv для переменных env, я также указываю версию компилятора Solidity, сеть, которую собираюсь использовать (в нашем случае goerli test network), и передаю свои конфиденциальные данные, которые кэшируются от нежелательного внимания переменными env. Я покажу, как найти, добавить и скрыть эти env-переменные в следующем шаге.

Добавление переменных env для скрытия конфиденциальных данных

API Alchemy

Для начала я создам пустой файл .env. Я помещу этот файл в папку wagmi-frontend, которую я скоро создам. Вы можете просто создать его в другом месте прямо сейчас и переместить в эту папку позже. Теперь, чтобы заполнить его, мне понадобится внешняя помощь от Alchemy. Если у вас нет учетной записи Alchemy, пожалуйста, зайдите на https://www.alchemy.com/ и создайте ее (это бесплатно). Теперь, поскольку у нас есть аккаунт Alchemy, мы перейдем на нашу приборную панель и создадим новый проект, нажав на кнопку +create app справа вверху. При создании приложения крайне важно выбрать Goerli для нашей сети, поскольку мы не собираемся использовать Ethereum Mainnet, так как не хотим тратить реальные деньги на практику. Теперь, когда мы создали наше приложение на Alchemy, мы нажмем кнопку view key справа на вкладке проекта и скопируем-вставим секции API KEY и HTTPS. Они оба понадобятся нам для нашего проекта.

Закрытый ключ Metamask

Теперь, для этого шага вам понадобится аккаунт metamask с фальшивыми деньгами для тестовой сети Goerli. Чтобы продолжить обучение, пожалуйста, установите расширение Metamask в свой браузер, запросите немного тестовых денег из крана, такого как этот https://goerlifaucet.com/ (вы можете войти и запросить деньги, используя свой аккаунт Alchemy, поскольку он у вас уже есть).

NB: Пожалуйста, используйте сгораемый кошелек. То есть, никогда не кладите реальные деньги на этот кошелек, не используйте его для производства или любых других целей, кроме практики. Лучше просто забыть и никогда не использовать этот кошелек после прохождения курса.

Теперь, чтобы получить приватный ключ, нажмите на три вертикальные точки справа от расширения metamask и выберите account details. там вы увидите кнопку, которая направит вас к вашему приватному ключу. Введите там свой пароль и получите приватный ключ. После того, как вы скопируете свой закрытый ключ, перейдем к нашему файлу .env и вставим туда всю информацию, которую мы получили на данный момент. Это должно выглядеть примерно следующим образом:

ALCHEMY_GOERLI_URL=https://eth-goerli.g.alchemy.com/somethingsomething
MY_PRIVATE_KEY= somethingsomethingmyprivatekey
ALCHEMY_ID=sthsthmyalchemyID
Вход в полноэкранный режим Выйти из полноэкранного режима

Не показывайте никому информацию в вашем файле .env, и если вы собираетесь использовать GitHub для своего проекта, пожалуйста, проверьте, что ваш файл .gitignore включает файлы .env, так что вы не будете публиковать эту жизненно важную информацию. Люди даже крадут фальшивые деньги, я слышал об этом.

Теперь, когда файл .env заполнен, мы можем написать наш смарт-контракт для развертывания.

Написание смарт-контракта

Теперь, когда мы создали структуру нашего проекта, нам нужен смарт-контракт для развертывания. Давайте создадим файл Wave.sol в папке contracts, которую мы создали, инициировав проект hardhat, и вставим в него следующий контракт:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Wave {
    string public name = "Murat";

     function setName(string memory _name) external {

        name = _name;

    }
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Что здесь происходит? Прежде всего, расширение .sol указывает на то, что это файл Solidity, то есть код, написанный внутри этого файла, написан на языке Solidity. В первой строке я указываю, какую лицензию я использую (в данном случае MIT, открытый исходный код), и версию компилятора для Solidity. В данном случае это означает, что все, что выше 0.8.0, проходит.

Я начинаю свой контракт с ключевого слова contract и даю ему имя Wave. Внутри него я определяю публичную строку и даю ей начальное значение Мурат, мое имя. Вы можете дать любое значение, какое захотите. Затем я пишу функцию setName и даю ей параметр типа string, который сохраняется в памяти. Затем я делаю ее внешней, чтобы ее можно было вызывать извне контракта. Все, что делает эта функция, это изменяет значение публичной строки, принимая значение, которое помещено в параметр функции. Обратите внимание, что параметр функции начинается с подчеркивания _name. Это не обязательно, но это соглашение, используемое в сообществе Solidity. Это помогает нам различать, что является фактической переменной, а что параметром как таковым.

Пока что не стоит слишком беспокоиться о коде Solidity, это руководство не посвящено написанию смарт-контрактов Solidity.

Теперь мы закончили работу над смарт-контрактом, давайте свяжем все вместе и развернем его в тестовой сети!

Развертывание смарт-контракта

Для того чтобы эти шаги сработали, вы должны использовать поддерживаемую версию nodeJS для hardhat. Обычно это версия LTS.

Перейдите в корень проекта и введите в терминале npx hardhat compile. Если все идет нормально, вам будет предложено Compiled 1 Solidity file successfully, если нет, введите npx hardhat clean и переразверните проект до успешного завершения.

Теперь, если вы снова просмотрите структуру папок, вы увидите, что появилась новая папка artifacts. Если вы перейдете в папку contracts внутри этой папки artifacts, вы увидите файл .json с именем, которое вы дали своему смарт-контракту. Мы будем использовать этот файл позже, это наш контракт abi (бинарный интерфейс приложения).

Теперь давайте вернемся и зайдем в папку scripts и добавим файл deploy.js со следующим кодом внутри:

const hre = require("hardhat");

async function main() {
  // We get the contract to deploy
  const [owner] = await hre.ethers.getSigners();
  //Here make sure you enter the name of the .sol file you've created in the contracts folder.
  const WaveContractFactory = await hre.ethers.getContractFactory("Wave");
  const WaveContract = await WaveContractFactory.deploy();
  await WaveContract.deployed();

  console.log("WaveContract deployed to:", WaveContract.address);
  console.log("WaveContract owner address:", owner.address);
}

main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
  });
Вход в полноэкранный режим Выйти из полноэкранного режима

Приведенный выше код обеспечит развертывание нашего кода. Как я уже упоминал в комментариях, просто убедитесь, что вы ввели имя смарт-контракта, который вы написали ранее.

Теперь в терминале npx hardhat run scripts/deploy.js --network goerli пишем следующее.

Если все прошло успешно, вам будет предложено что-то вроде:

WaveContract deployed to: somehweresomething
WaveContract owner address: somehweresomethingelse
Войти в полноэкранный режим Выйти из полноэкранного режима

Сохраните эти адреса в надежном и скрытом месте, мы будем использовать их позже.

Поздравляем! Вы только что развернули смарт-контракт на блокчейне! Вы даже можете проверить свой контракт, перейдя по адресу https://goerli.etherscan.io/ и вставив адрес, по которому этот контракт был развернут!

Даже для простого контракта это было очень много движущихся частей, так что похлопайте себе по спине. Теперь мы займемся фронтендом, то есть тем, как мы заставим пользователей взаимодействовать с контрактом, который мы только что развернули.

Часть вторая: Создание фронтенда

Установка зависимостей

В этом проекте я буду использовать reactJS, поэтому давайте перейдем в нашу корневую папку и создадим проект react, введя npx create-react-app wagmi-frontend в терминале.

После этого наша структура папок должна выглядеть следующим образом:

-Wagmi-project (root)
--artifacts
--cache
-contracts
-node_modules
-scripts
-test
-wagmi-frontend
-.gitignore
-hardhat-config.js
-package.json
-README.md
-yarn.lock
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь зайдем в эту новую папку wagmi-frontend и установим ethersJS, а также wagmi.sh. Для установки библиотеки ethersJS я напишу в терминале следующую команду yarn add ethers, а для установки wagmi.sh я напишу следующую yarn add wagmi ethers.

Я также устанавливаю buffer, поскольку полифиллы node больше не поставляются с webpack, установка этого пакета — самое простое решение, которое я нашел для работы с ошибкой, которую мы увидели бы, если бы у нас не было buffer. Чтобы установить buffer, я пишу следующее в командной строке yarn add buffer. Затем я перейду к моему файлу index.js внутри wagmi-frontend/src/ и потребую buffer в таком виде window.Buffer = require("buffer/").Buffer; в верхней части компонента. Теперь мой файл index.js выглядит следующим образом:

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
window.Buffer = require("buffer/").Buffer;
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

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

Наконец, я установлю gh-pages, поскольку я хочу развернуть проект на Github Pages. Для этого я напишу следующую команду в терминале yarn add gh-pages.

Теперь, когда мы закончили с установкой зависимостей, мы можем посмотреть, как использовать их для создания фронтенда для взаимодействия с нашим смарт-контрактом.

Написание фронтенда

Поскольку мы находимся внутри папки wagmi-frontend, наша структура папок (исключая все, что не относится к wagmi-frontend) должна выглядеть следующим образом:

-node_modules
-public
-src
-.env
-.gitignore
-hardhat-config.js
-package.json
-README.md
-yarn.lock
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь я добавлю еще несколько папок и файлов в эту папку wagmi-frontend. Я добавлю 2 папки с именами contracts и style, а также файл Profile.js. Прежде чем продолжить, я создам файл Wave.json в папке contracts, которую я только что создал. Чтобы заполнить этот файл, мне нужно вернуться в мою корневую папку (не в папку wagmi-frontend, в которой мы сейчас находимся, а в папку, в которой она также содержится). Там, как вы помните, у нас была папка artifacts, я войду в нее и найду папку contracts. Внутри папки contracts находится файл Wave.json, который был создан hardhat. Я скопирую все, что в нем находится.

После копирования содержимого этого файла Wave.json я вернусь в папку wagmi-frontend, войду в src, затем в папку contracts и создам там еще один файл Wave.json. В этот файл я вставлю все, что скопировал. Этот файл содержит abi нашего смарт-контракта.

В папке style я создам файл profile.css и добавлю в него следующее содержимое (не беспокойтесь об этом, это просто для того, чтобы кнопки выглядели немного красивее. В конце концов, это не пост о написании CSS):

.btn {
  display: flex;
  flex-wrap: wrap;
  width: 150px;
  margin-bottom: 10px;
  padding: 5px;
}

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

Я также зайду в файл App.css в папке src и добавлю следующее содержимое:

.App {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background: black;
  color: white;
  height: 100vh;
}

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

Теперь я могу перейти в файл App.js, удалить все внутри него и написать свой собственный код.

App.js

Я начну с импорта зависимостей для приложения:

import { useState } from "react";
import { ethers, utils } from "ethers";
import abi from "./contracts/Wave.json";
import Profile from "./Profile";
import "./App.css";
import {
  WagmiConfig,
  createClient,
  defaultChains,
  configureChains,
} from "wagmi";

import { alchemyProvider } from "wagmi/providers/alchemy";
import { publicProvider } from "wagmi/providers/public";

import { CoinbaseWalletConnector } from "wagmi/connectors/coinbaseWallet";
import { InjectedConnector } from "wagmi/connectors/injected";
import { MetaMaskConnector } from "wagmi/connectors/metaMask";
import { WalletConnectConnector } from "wagmi/connectors/walletConnect";
Вход в полноэкранный режим Выход из полноэкранного режима

Вы видите, что я буду использовать хук useState из React, библиотеку ethers, контракт abi, который мы сохранили в файле Wave.json, компонент Profile, который мы создадим позже, файл App.css, зависимости для wagmi, которые включают провайдеров наряду с коннекторами кошельков. После того, как это будет сделано, я добавлю следующие строки кода прямо под ним:


const alchemyId = process.env.ALCHEMY_ID;

// Configure chains & providers with the Alchemy provider.
// Two popular providers are Alchemy (alchemy.com) and Infura (infura.io)
const { chains, provider, webSocketProvider } = configureChains(defaultChains, [
  alchemyProvider({ alchemyId }),
  publicProvider(),
]);

// Set up client
const client = createClient({
  autoConnect: true,
  connectors: [
    new MetaMaskConnector({ chains }),
    new CoinbaseWalletConnector({
      chains,
      options: {
        appName: "wagmi",
      },
    }),
    new WalletConnectConnector({
      chains,
      options: {
        qrcode: true,
      },
    }),
    new InjectedConnector({
      chains,
      options: {
        name: "Injected",
        shimDisconnect: true,
      },
    }),
  ],
  provider,
  webSocketProvider,
});

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

Эти части также можно найти в документации по wagmi. Что мы делаем здесь, так это берем наш Alchemy Id, который мы сохранили в нашем .env файле, а затем настраиваем клиент для различных вариантов кошелька. Вы видите, что здесь у нас есть Metamask, Coinbase, WalletConnector и Injected. После того как мы указали эти части, мы можем начать писать нашу главную функцию, так что давайте сделаем это.

const App = () => {
  const [isWalletConnected, setIsWalletConnected] = useState(false);
  const [userName, setUserName] = useState("");
  const [displayedUserName, setDisplayedUserName] = useState("initial name");
  const [error, setError] = useState(null);
  const contractAddress = "theaddressthatourcontracthasbeendeployedtocomeshere";
  const contractABI = abi.abi;
  }
Войти в полноэкранный режим Выход из полноэкранного режима

Как видите, у меня есть константы для изменения состояния, адрес контракта, который мы получили, когда развернули наш контракт на (тестовом) блокчейне, и abi контракта, который мы импортировали из нашего файла Wave.json.

Далее я добавлю необходимые функции. Давайте посмотрим, что они делают:


  const handleInput = (name) => {
    setUserName(name.target.value);
  };

  const handleChild = (status) => {
    console.log(status);
    status ? setIsWalletConnected(true) : setIsWalletConnected(false);
  };

  const handleClick = async (e) => {
    e.preventDefault();
    if (window.ethereum) {
      const provider = new ethers.providers.Web3Provider(window.ethereum);
      const signer = provider.getSigner();
      const waveContract = new ethers.Contract(
        contractAddress,
        contractABI,
        signer
      );

      const txn = await waveContract.setName(
        utils.formatBytes32String(userName)
      );
      console.log("setting user name");
      await txn.wait();
      console.log("user name set", txn.hash);
      setDisplayedUserName(userName);
    }
  };
Вход в полноэкранный режим Выход из полноэкранного режима

Функция handleInput проста для понимания. Мы будем принимать ввод пользователя, устанавливать его в состояние и отображать в пользовательском интерфейсе.

Далее, функция handleClick. Она асинхронная, и проверяет, есть ли в браузере кошелек, затем с помощью библиотеки ethersJS работает с провайдерами и подписчиками. txn — это транзакция, она преобразует имя пользователя в байт32, чтобы EVM (Ethereum Virtual Machine) могла его понять. Затем он ждет, пока транзакция будет добыта, и затем устанавливает имя пользователя.

Теперь давайте рассмотрим последние фрагменты нашего компонента App.js:

  let userInteraction;
  if (isWalletConnected === true) {
    userInteraction = (
      <div>
        <input onChange={handleInput} type="text" />
        <button onClick={handleClick}>Wave</button>
        <p> {displayedUserName} waved!</p>
      </div>
    );
  }

  return (
    <div className="App">
      <h1>Wagmi Project</h1>

      {userInteraction}
      <WagmiConfig client={client}>
        <Profile handleChild={handleChild} />
      </WagmiConfig>
    </div>
  );
};

export default App;
Вход в полноэкранный режим Выход из полноэкранного режима

Сначала я определяю пустую переменную userInteraction. Затем, в зависимости от статуса подключения кошелька, я заполняю ее соответствующим пользовательским интерфейсом. Если кошелек подключен, я отображу поле ввода и кнопку. Если кошелек не подключен, их там не будет.

В операторе возврата я передаю вышеприведенный условный оператор и вызываю наш дочерний компонент Profile.js с handleChild, переданным в качестве props, как я уже упоминал ранее.

Чтобы убедиться, что все на месте, давайте посмотрим на весь компонент App.js:

import { useState, useEffect } from "react";
import { ethers, utils } from "ethers";
import abi from "./contracts/Wave.json";
import Profile from "./Profile";
import "./App.css";
import {
  WagmiConfig,
  createClient,
  defaultChains,
  configureChains,
} from "wagmi";

import { alchemyProvider } from "wagmi/providers/alchemy";
import { publicProvider } from "wagmi/providers/public";

import { CoinbaseWalletConnector } from "wagmi/connectors/coinbaseWallet";
import { InjectedConnector } from "wagmi/connectors/injected";
import { MetaMaskConnector } from "wagmi/connectors/metaMask";
import { WalletConnectConnector } from "wagmi/connectors/walletConnect";

const alchemyId = process.env.ALCHEMY_ID;

// Configure chains & providers with the Alchemy provider.
// Two popular providers are Alchemy (alchemy.com) and Infura (infura.io)
const { chains, provider, webSocketProvider } = configureChains(defaultChains, [
  alchemyProvider({ alchemyId }),
  publicProvider(),
]);

// Set up client
const client = createClient({
  autoConnect: true,
  connectors: [
    new MetaMaskConnector({ chains }),
    new CoinbaseWalletConnector({
      chains,
      options: {
        appName: "wagmi",
      },
    }),
    new WalletConnectConnector({
      chains,
      options: {
        qrcode: true,
      },
    }),
    new InjectedConnector({
      chains,
      options: {
        name: "Injected",
        shimDisconnect: true,
      },
    }),
  ],
  provider,
  webSocketProvider,
});

const App = () => {
  const [isWalletConnected, setIsWalletConnected] = useState(false);
  const [userName, setUserName] = useState("");
  const [displayedUserName, setDisplayedUserName] = useState("initial name");
  const [error, setError] = useState(null);
  const contractAddress = "0x17c5A76a5D6db7740821425aFa029B3494DeecaB";
  const contractABI = abi.abi;

  const handleInput = (name) => {
    setUserName(name.target.value);
  };

  const handleChild = (status) => {
    console.log(status);
    status ? setIsWalletConnected(true) : setIsWalletConnected(false);
  };

  const handleClick = async (e) => {
    e.preventDefault();
    if (window.ethereum) {
      const provider = new ethers.providers.Web3Provider(window.ethereum);
      const signer = provider.getSigner();
      const waveContract = new ethers.Contract(
        contractAddress,
        contractABI,
        signer
      );

      const txn = await waveContract.setName(
        utils.formatBytes32String(userName)
      );
      console.log("setting user name");
      await txn.wait();
      console.log("user name set", txn.hash);
      setDisplayedUserName(userName);
    }
  };

  let userInteraction;
  if (isWalletConnected === true) {
    userInteraction = (
      <div>
        <input onChange={handleInput} type="text" />
        <button onClick={handleClick}>Wave</button>
        <p> {displayedUserName} waved!</p>
      </div>
    );
  }

  return (
    <div className="App">
      <h1>Wagmi Project</h1>

      {userInteraction}
      <WagmiConfig client={client}>
        <Profile handleChild={handleChild} />
      </WagmiConfig>
    </div>
  );
};

export default App;
Вход в полноэкранный режим Выход из полноэкранного режима

Мы закончили с компонентом App.js. Я знаю, что это много, но у нас остался еще один компонент, дочерний, Profile.js. После этого у нас все готово.

Написание дочернего компонента

Я начинаю с импорта всего, что необходимо импортировать в самом начале:

import { React, useEffect } from "react";
import {
  useAccount,
  useConnect,
  useDisconnect,
  useEnsAvatar,
  useEnsName,
} from "wagmi";
import "./style/profile.css";
Вход в полноэкранный режим Выйти из полноэкранного режима

Далее идет главная функция нашего дочернего компонента с handleChild, которая была передана от родителя в качестве реквизита:

const Profile = ({ handleChild }) => {
  const { address, connector, isConnected } = useAccount();
  const { data: ensAvatar } = useEnsAvatar({ addressOrName: address });
  const { data: ensName } = useEnsName({ address });
  const { connect, connectors, error, isLoading, pendingConnector } =
    useConnect();
  const { disconnect } = useDisconnect();

  useEffect(() => {
    console.log(isConnected);

    if (isConnected === true) {
      handleChild(true);
    }
  });
Вход в полноэкранный режим Выход из полноэкранного режима

Вы заметите, что я использую деструктурированные реквизиты с фигурными скобками вокруг них, я нахожу это более читабельным.

Здесь у нас есть наши константы, которые можно найти в документации к wagmi.sh, помогающие нам использовать его хуки.

В хуке useEffect я проверяю, подключен ли пользователь. Если да, то я отправляю данные родителю, вызывая функцию handleChild. Помните, что она устанавливает состояние кошелька как подключенное в родительском компоненте. Далее у меня есть условный оператор, который проверяет, подключен ли пользователь. Если да, то я отображаю адрес кошелька, который подключен, и его название (например, Metamask или Coinbase):


  if (isConnected) {
    return (
      <div>
        {/* <img src={ensAvatar} alt="ENS Avatar" /> */}
        <div>{ensName ? `${ensName} (${address})` : address}</div>
        <div>Connected to {connector.name}</div>
        <button onClick={disconnect}>Disconnect</button>
      </div>
    );
  }
Войти в полноэкранный режим Выход из полноэкранного режима

В завершение у меня есть заявление о возврате. Он довольно прост в объяснении:

  return (
    <div>
      {connectors.map((connector) => (
        <button
          className="btn"
          disabled={!connector.ready}
          key={connector.id}
          onClick={() => connect({ connector })}
        >
          {connector.name}
          {!connector.ready && " (unsupported)"}
          {isLoading &&
            connector.id === pendingConnector?.id &&
            " (connecting)"}
        </button>
      ))}

      {error && <div>{error.message}</div>}
    </div>
  );
};

export default Profile;
Войти в полноэкранный режим Выход из полноэкранного режима

Вот, собственно, и все. Теперь, если мы перейдем в папку wagmi-frontend и введем yarn start (или npm run start, если вы используете npm), мы увидим, что приложение запущено.

Заключительные мысли

Поздравляем! Вы закончили этот учебник. Вы можете найти исходный код этого руководства здесь=> https://github.com/muratcan-yuksel/wagmi-post . Я знаю, что было много движущихся частей и вещей, которые нужно было сделать, но я надеюсь, что вам понравилось. Если у вас есть вопросы, не стесняйтесь обращаться ко мне в Twitter или на Github.

Сохраняйте спокойствие и счастливого взлома!

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