Web3Modal을 dApp에 통합하기
소개
Web3Modal은 개발자가 간단하고 사용자 정의 가능한 구성으로 dApp에서 여러 공급자를 지원할 수 있도록 도와주는 사용하기 쉬운 라이브러리입니다. 지갑 연결, 트랜잭션 수행, 계정 관리를 쉽게 할 수 있습니다.
In this guide, you will use the web3Modal library to integrate multiple wallets such as Kaia Wallet, Klip, Metamask, Coinbase Wallet, etc. into your dApp built on the Kaia Network.
전제 조건
- 작동하는 리액트 프로젝트(
npx create-react-app 프로젝트 이름
을 실행하여) - Install the necessary wallets (Kaia Wallet, Coinbase Wallet, and Metamask).
- RPC 엔드포인트: 지원되는 [엔드포인트 공급자] 중 하나에서 받을 수 있습니다(../../../references/public-en.md).
- Test KAIA from Faucet: fund your account with sufficient KAIA.
Web3Modal 및 지갑 공급자 옵션 설정하기
1단계: Web3Modal 및 이더리움 라이브러리 설치하기
블록체인과 상호작용하기 위해 Web3Modal과 원하는 라이브러리를 설치합니다. In this tutorial, we will be installing @klaytn/web3modal which was derived from Web3Modal and modified to add Kaia Wallet and Klip wallet. 또한, 이 튜토리얼에서는 ethers.js를 사용하여 Kaia 블록체인과 상호작용할 것입니다.
npm install @klaytn/web3modalnpm install --save ethers
2단계: 지갑 공급자 옵션으로 Web3Modal 인스턴스화하기
원하는 지갑 서비스 제공업체를 설치합니다. Here we install Kaia Wallet, Klip and Coinbase wallet providers.
npm install --save @coinbase/wallet-sdknpm install --save @klaytn/kaikas-web3-providernpm install --save @klaytn/klip-web3-provider
App.js
파일에서 CoinbaseWalletSDK, KaikasWeb3Provider, KlipWeb3Provider를 임포트하고 다양한 프로바이더 옵션을 인스턴스화하여 여러분의 dApp과 연동합니다.
import CoinbaseWalletSDK from '@coinbase/wallet-sdk';import { KaikasWeb3Provider } from "@klaytn/kaikas-web3-provider";import { KlipWeb3Provider } from "@klaytn/klip-web3-provider";export const providerOptions = { coinbasewallet: { package: CoinbaseWalletSDK, options: { appName: "Web 3 Modal Demo", infuraId: process.env.INFURA_KEY } }, walletconnect: { package: WalletConnect, options: { infuraId: process.env.INFURA_KEY } }};const providerOptions = { coinbasewallet: { package: CoinbaseWalletSDK, // required options: { appName: "Web3Modal Kaia dApp", // required infuraId: "NFURA_KEY", // required rpc: "https://public-en.node.kaia.io", // Optional if `infuraId` is provided; otherwise it's required chainId: 1001, // Optional. It defaults to 1 if not provided darkMode: false // Optional. Use dark theme, defaults to false } }, klip: { package: KlipWeb3Provider, //required options: { bappName: "Web3Modal Kaia dApp", //required rpcUrl: "https://public-en.node.kaia.io" //required }}, kaikas: { package: KaikasWeb3Provider // required }};
3단계: Web3Modal 인스턴스화
그런 다음 공급자 옵션을 전달하여 Web3Modal을 인스턴스화합니다.
import Web3Modal from "@klaytn/web3modal";const web3Modal = new Web3Modal( { cacheProvider: true, providerOptions, } )
지갑 연결 설정하기
사용자 지갑에 연결을 설정하려면 Web3Modal 인스턴스에서 connect()
메서드를 호출합니다. 이 작업을 비동기 함수로 래핑하고 검색된 공급자를 상태에 저장하여 앱 전체에서 재사용하는 것이 좋습니다.
import { ethers } from 'ethers';import { useState } from 'react';function App() { const [provider, setProvider] = useState(); const connectWallet = async () => { try { const web3ModalProvider = await web3Modal.connect(); // this guide uses ethers version 6.3.0. const ethersProvider = new ethers.BrowserProvider(web3ModalProvider); // for ethers version below 6.3.0. // const provider = new ethers.providers.Web3Provider(web3ModalProvider); setProvider(web3ModalProvider); } catch (error) { console.error(error); } }; return ( <div className="App"> <button onClick={connectWallet}>Connect Wallet</button> </div> );}
유틸리티 함수 설정
이 가이드에서는 truncateAddress()
및 toHex()
와 같은 유틸리티 함수를 사용하겠습 니다. truncateAddress()
함수는 유효한 주소를 받아 전달된 주소의 읽기 쉬운 형식을 반환합니다. 반면에 toHex()
함수는 숫자를 16진수로 변환합니다. 아래 단계는 프로젝트에서 유틸리티 함수를 설정하고 사용하는 방법을 보여줍니다.
1단계: src
루트 폴더에 utils.js
파일을 생성합니다.
새로 만든 utils.js 파일에 다음 코드를 붙여넣습니다.
export const truncateAddress = (address) => { if (!address) return "No Account"; const match = address.match( /^(0x[a-zA-Z0-9]{2})[a-zA-Z0-9]+([a-zA-Z0-9]{4})$/ ); if (!match) return address; return `${match[1]}…${match[2]}`; }; export const toHex = (num) => { const val = Number(num); return "0x" + val.toString(16); };
2단계: App.js
파일에서 함수를 가져옵니다.
import { truncateAddress, toHex } from "./utils";
연결, 계정, 네트워크 정보에 액세스하기
현재 Web3Modal은 연결된 계정 및 네트워크 데이터 검색과 같은 이더리움 상호 작용에 대한 기본 지원을 제공하지 않습니다. 사용자의 주소나 연결된 네트워크 ID를 읽으려면 이더리움 라이브러리에 직접 해당 정보를 요청해야 합니다. 이 가이드에서는 ethers.js를 사용하여 해당 정보를 가져올 것입니다. 한 가지 방법은 사용자를 dApp에 연결할 때 이 데이터를 가져와 저장하는 것입니다.
const [provider, setProvider] = useState();const [account, setAccount] = useState();const [chainId, setChainId] = useState();const connectWallet = async () => { try { const web3ModalProvider = await web3Modal.connect(); // this guide uses ethers version 6.3.0. const ethersProvider = new ethers.BrowserProvider(web3ModalProvider); // for ethers version below 6.3.0. // const provider = new ethers.providers.Web3Provider(web3ModalProvider); const accounts = await ethersProvider.listAccounts(); const network = await ethersProvider.getNetwork(); setProvider(provider); if (accounts) setAccount(accounts[0]); setChainId(network.chainId.toString()); } catch (error) { console.error(error); }};return ( <div className="App"> <button onClick={connectWallet}>Connect Wallet</button> <div>Connected To Chain ID: ${chainId}</div> <div>Wallet Address: ${truncateAddress(account)}</div> </div>);
지갑 연결 해제하기
지갑과의 연결 해제는 web3Modal 인스턴스에서 clearCachedProvider()
메서드를 사용하여 수행됩니다. 또한 상태를 새로 고쳐 이전에 저장된 연결 데이터를 지우는 것도 좋은 방법 중 하나입니다.
function App() { const disconnect = async () => { await web3Modal.clearCachedProvider(); refreshState(); };// refresh stateconst refreshState = () => { setAccount(); setChainId();// make sure to add every other state variable declared here.} return ( <div className="App"> <button onClick={disconnect}>Disconnect</button> </div> );}
사용자가 상호작용할 때 dApp 상태가 변경된다는 점을 명심해야 하며, 이에 대응하여 릴리스되는 이벤트를 구독하는 것이 가장 좋습니다. 이러한 이벤트에 대한 구독으로 사용 효과 후크를 생성하여 변경 사항에 적절히 대응할 수 있도록 하세요.
useEffect(() => { if (provider?.on) { const handleAccountsChanged = (accounts) => { setAccount(accounts); }; const handleChainChanged = (chainId) => { setChainId(chainId); }; const handleDisconnect = () => { disconnect(); }; provider.on("accountsChanged", handleAccountsChanged); provider.on("chainChanged", handleChainChanged); provider.on("disconnect", handleDisconnect); return () => { if (provider.removeListener) { provider.removeListener("accountsChanged", handleAccountsChanged); provider.removeListener("chainChanged", handleChainChanged); provider.removeListener("disconnect", handleDisconnect); } }; } }, [provider]);
네트워크 전환 또는 사용자 지정 네트워크 추가
앞서 설명한 바와 같이 Web3Modal은 이더리움 상호작용을 기본적으로 지원하지 않습니다. 네트워크를 추가하거나 전환하려면 이더리움 라이브러리에 직접 요청(EIP-3085 또는 EIP-3326을 통해)해야 합니다. 다음은 네트워크 전환을 요청하고 사용자 지갑에 해당 네트 워크가 없는 경우 대체 네트워크로 추가하는 예시입니다:
const switchNetwork = async () => { if (!provider) return; try { await provider.request({ method: "wallet_switchEthereumChain", params: [{ chainId: toHex(8217) }], }); } catch (switchError) { // This error code indicates that the chain has not been added to MetaMask. if (switchError.code === 4902) { try { await provider.request({ method: "wallet_addEthereumChain", params: [ { chainId: toHex(1001), chainName: "Kairos Testnet", rpcUrls: ["https://public-en-kairos.node.kaia.io"], blockExplorerUrls: ["https://kairos.kaiascan.io/"], }, ], }); } catch (addError) { throw addError; } } } };return ( <div className="App"> <button onClick={switchNetwork}>Switch Network</button> </div>)