Как подключить web3modal к сайту. Новый и старый вариант
22 июня 2023 г.
Web3modal v 2
Перед использованием нужно проверить актуальность, так как библиотеки обновляются.
Ниже представлен вариант подключения web3modal к React.
Новый web3modal в связке с wagmi показался мне очень удобным в настройке и использовании. В документации все довольно понятно объясняется, но приведу для наглядности свои примеры настроек.
web3modal v2 https://web3modal.com/
wagmi https://wagmi.sh/
Project id , необходимый для настройки, можно получить здесь https://cloud.walletconnect.com/sign-in
Настройка файла index.js,
Из web3modal мы импортирует Web3Modal. Из wagmi configureChains, createClient, WagmiConfig.
1import React from 'react';2import * as ReactDOMClient from "react-dom/client";3import { Provider } from "react-redux";4import { EthereumClient, w3mConnectors, w3mProvider } from '@web3modal/ethereum'5import { Web3Modal } from '@web3modal/react'6import { configureChains, createConfig, WagmiConfig } from 'wagmi'7import { setupStore } from "./redux";8import { chains } from "./constants/chains.config";9import { config } from "./app-config";10import './index.scss';11import ErrorBoundry from './components/error-boundry';12import App from './App';1314const store = setupStore();1516// Wagmi client17const { publicClient } = configureChains(chains, [w3mProvider({ projectId: config.walletConnectId })])1819const wagmiConfig = createConfig({20 autoConnect: true,21 connectors: w3mConnectors({ projectId: config.walletConnectId, version: 1, chains }),22 publicClient23})2425// Web3Modal Ethereum Client26const ethereumClient = new EthereumClient(wagmiConfig, chains)2728const container = document.getElementById("root");29const root = ReactDOMClient.createRoot(container);3031root.render(32 <>33 <WagmiConfig config={wagmiConfig}>34 <Provider store={store}>35 <ErrorBoundry>36 <App />37 </ErrorBoundry>38 </Provider>39 </WagmiConfig>4041 <Web3Modal42 projectId={config.walletConnectId}43 ethereumClient={ethereumClient}44 themeMode={"light"}45 themeColor={"default"}46 // Select a network before connecting47 enableNetworkView={true}48 />49 </>50);51
Файл app-config.js
1export const isMainnet = false;23export const config = {4 lang: 'ru',5 walletConnectId: "",6 contractAddress: "",7 version: "1.0.0",8}9
Файл chains.config.js
Список сетей я вынесла в отдельный файл, этого можно и не делать. Wagmi предоставляет большую часть сетей с полной конфигурацией, поэтому необходимые я импортировала оттуда.
1import { isMainnet } from "../app-config";2import { avalanche, bsc, mainnet, fantom, fantomTestnet, polygon, gnosis, harmonyOne, bscTestnet } from 'wagmi/chains';34export const defaultChain = isMainnet ? bsc : bscTestnet;5export const chains = isMainnet ? [{6 ...mainnet7}, {8 ...avalanche9}, {10 ...bsc,11}, {12 ...polygon13}, {14 ...fantom15}, {16 ...gnosis17}, {18 ...harmonyOne19}, {20 id: 195,21 name: 'Tron Mainnet',22 network: 'tron-mainnet',23 nativeCurrency: {24 decimals: 18,25 name: 'Tron',26 symbol: 'TRX',27 },28 rpcUrls: {29 default: {30 http: ['https://api.trongrid.io']31 },32 public: {33 http: ['https://api.trongrid.io']34 },35 },36 blockExplorers: {37 etherscan: {38 name: 'tronscan',39 url: 'https://tronscan.org/'40 },41 default: {42 name: 'tronscan',43 url: 'https://tronscan.org/'44 },45 },46}] : [{47 ...fantomTestnet48}, {49 id: 1666700000,50 name: 'Harmony Testnet',51 network: 'harmony-testnet',52 nativeCurrency: {53 decimals: 8,54 name: 'Harmony',55 symbol: 'ONE',56 },57 rpcUrls: {58 default: {59 http: ['https://api.s0.b.hmny.io']60 },61 public: {62 http: ['https://api.s0.b.hmny.io']63 },64 },65 blockExplorers: {66 etherscan: {67 name: 'explorer.harmony',68 url: 'https://explorer.ps.hmny.io/'69 },70 default: {71 name: 'explorer.harmony',72 url: 'https://explorer.ps.hmny.io/'73 },74 },75}, {76 ...bscTestnet,77}]
Подключение к Metamask.
Для подключения к кошельку можно создать как свою кнопку, так использовать готовую от web3Modal. Я использую обычную кнопку.
На момент написания этого текста, safari не поддерживало web3 поэтому мы не подключаемся в нем к кошельку. Лучше уведомить об этом пользователя.
1import React from "react";23const Home = () => {4 const onConnect = async() => {5 try {6 var isSafari = /constructor/i.test(window.HTMLElement) || (function (p) {7 return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || (typeof safari !== 'undefined' && window['safari'].pushNotification));89 if (isSafari) {10 return false;11 }1213 await open();1415 } catch(e) {16 console.log('Connect error: ', e)17 }18 }192021 return (22 <div className="page_container">23 <button24 className="btn"25 onClick={connectHandle}>26 Connect to Metamask27 </button>28 </div>29 )30}3132export default Home;
Disconnect
1import React from "react";23const Home = () => {4 const onDisconnect = async() => {5 try {6 await disconnect();7 await localStorage.clear();8 dispatch(setSign({data: ""}));9 dispatch(setSignError({data: ""}));10 } catch(e) {11 if(isError) {12 console.log("Disconnect error: ", error)13 }14 }15 }1617 return (18 <div className="page_container">19 <button20 className="btn"21 onClick={() => {onDisconnect()}}>22 Disconnect23 </button>24 </div>25 )26}2728export default Home;
Web3modal v 1
Инициализация web3Modal
Infura id вы можете получить здесь https://www.infura.io/
1const initWeb3Modal = () => {2 try {3 const newWeb3Modal = new Web3Modal({4 cacheProvider: true,5 providerOptions: {6 walletconnect: {7 package: WalletConnectProvider,8 options: {9 rpc: {10 56: 'https://bscrpc.com',11// здесь может быть большой список1213 },14 infuraId: '',15 bridge: 'https://bridge.walletconnect.org',16 chainId: 56, // вы можете указать переменную17 qrcode: true,18 qrcodeModalOptions: {19 mobileLinks: [20 'metamask'21 ],22 },23 }24 }25 }26 })2728 return newWeb3Modal29 } catch (error) {30 console.log(error)31 }
Также в options можно добавить network
Connect to metamask
1const connectWallet = async () => {2 try {3 const web3modal = initWeb3Modal()4 const provider = web3modal && await web3modal.connect();5 const library = new ethers.providers.Web3Provider(provider, "any") // any ставит опцию anyNetwork: true, если ее убрать значение станет false6 const signer = await library.getSigner()7 const network = await library.getNetwork()8 library.pollingInterval = 12000;9 const account = await library.listAccounts()10 const signerAddress = account[0]11 const balance = await library.getBalance(signerAddress)12 return { provider, library, signer, signerAddress, network, balance }1314 } catch (er) {15 console.log(er)16 }17}18
Disconnect
1const onDisconnect = async () => {2 const web3modal = initWeb3Modal()3 await web3modal.clearCachedProvider();4}5
Принудительно сменить сеть, например, при коннекте можно через
1await provider.request({2 method: "wallet_switchEthereumChain",3 params: [{4 chainId: 15 }],6 });7
Документация metamask в которой описаны этот и другие методы https://docs.metamask.io/wallet/reference/rpc-api/