ABOUT ME

-

Today
-
Total
-
  • web3-react로 DApp에 지갑 연동 구현하기
    Study/Blockchain 2022. 3. 4. 17:05
    반응형

     

    이더리움 DApp을 개발하기 위해서 블록체인 지갑 연동은 필수라고 할 수 있다.

    이더리움 기반 블록체인 지갑에는 여러 종류가 있는데 레저 나노, 트레저원, 메타마스크, 마이이더월렛, 트러스트월렛 등이 있다.

    지갑을 연동하기 위해서는 지갑의 개발 문서를 참고하여 각각 지갑마다 연동 기능을 개발할 수 있지만,

    같은 이더리움 네트워크에서 동작하는 지갑이라면 web3-react를 사용해서 쉽게 지갑 연동을 하고 관련 상태들을 관리할 수 있다.

     

    ✨ web3-react

    A simple, maximally extensible, dependency minimized framework for building modern Ethereum dApps

    단순하고, 최대 확장 가능하며, 의존성을 최소화한 이더리움 디앱 빌딩 프레임워크.

    한마디로 이더리움 디앱 개발에 사용 가능한 React 기반 프레임워크라고 할 수 있다.

    React의 Context를 이용해서 DApp과 관련된 데이터(ex. 사용자의 현재 계정)를 최신 상태로 유지해주는 상태 라이브러리이며,

    앞서 말한 지갑 연동 뿐만 아니라 스마트컨트랙트와의 상호작용에도 사용할 수 있다.

     

    이번 포스팅에서는 web3-react를 사용해서 메타마스크(Metamask) 지갑을 어떻게 연동하는지 작성해보고자 한다.

    그리고 참고로 이 포스팅은 web3-react v6 버전을 기반으로 작성하고 있다. 현재 포스팅을 작성하는 날 기준으로 베타 버전으로 v8이 업데이트됐다. v8 버전에서는 connectors와 상태 관리 패턴이 새롭게 업그레이드된 것 같다. 좀 더 안정화되고 나면 v8 버전으로 업그레이드해봐야 할 것 같다.

     

    📍 패키지 설치

    yarn add @web3-react/core @web3-react/injected-connector ethers

     

    📍 Web3ReactProvider 컴포넌트 생성 및 getLibrary 함수 구현

    Web3ReactProvider 컴포넌트는 web3-react를 사용하기 위한 React Conext Provider 컴포넌트이다.

    이 컴포넌트는 React 루트 앱 컴포넌트를 감싸줘야 하고, props로 getLibrary 함수를 전달해줘야 한다.

    getLibrary 함수는 web3 라이브러리 객체를 인스턴스화 해주는 기능을 한다.

    ethers 라이브러리를 함께 사용해서 프로젝트를 진행하기 위해서 ethers에서 제공하는 web3 provider를 사용하고자 했다.

    새로 Web3Provider 객체를 생성해서 리턴해주면 된다.

    (타입스크립트로 작성했는데 티스토리에서 제공하는 코드 블럭이 자바스크립트밖에 없어서 ㅠㅠ 제대로 코드가 포맷팅 되지 않는 점이 아쉽다.)

     

    import React from 'react';
    import { Web3ReactProvider } from '@web3-react/core';
    import { ethers } from 'ethers';
    
    const App = () => {
        const getLibrary = (provider): ethers.providers.Web3Provider => {
          const library = new ethers.providers.Web3Provider(provider);
          library.pollingInterval = 12000;
          return library;
        };
    
        return (
            <Web3ReactProvider getLibrary={getLibrary}>
              <App />
            </Web3ReactProvider>
        );
    };
    
    ReactDOM.render(<App />, document.getElementById('app'));

     

    📍 useWeb3React 로 DApp context에 접근

    web3-react에서는 useWeb3React라는 hook을 제공하는데 함수 컴포넌트 내에서 DApp과 관련된 context 변수에 접근할 수 있다.

     

    const {connector, library, chainId, account, active, error, activate, deactivate } =  useWeb3React()

    해당 context의 자세한 인터페이스는 아래와 같다.

    • connector: 현재 dapp에 연결된 wallet의 connector
    • library: web3 provider
    • chainId: dapp에 연결된 account의 chainId
    • account: dapp에 연결된 account address
    • active: dapp 유저의 account가 연결된 상태
    • activate: dapp wallet 연결 함수
    • deactivate: dapp wallet 연결 해제 함수
    interface Web3ReactContextInterface<T = any> {
      activate: (
        connector: AbstractConnectorInterface,
        onError?: (error: Error) => void,
        throwErrors?: boolean
      ) => Promise<void>
      deactivate: () => void
      setError: (error: Error) => void
    
      connector?: AbstractConnectorInterface
      library?: T
      chainId?: number
      account?: null | string
    
      active: boolean
      error?: Error
    }

     

    📍 connector 생성 및 지갑 연결/해제

    지갑을 연동하기 위해서는 연동하고자 하는 지갑에 해당하는 connector를 가져와서 activate 함수에 전달해야 한다.

    메타마스크 지갑을 연동하기 위해서는 @web3-react/injected-connector 패키지에 있는 connector를 사용해야 한다.

    supportedChainIds에는 지원하고자 하는 체인의 id를 배열로 넣어주면 되는데, 생략해도 괜찮다.

    메타마스크 지갑 외에 다른 이더리움 지갑을 연동하고자 한다면 이 링크를 참고해서 connector 객체를 생성하면 된다.

     

    activate 함수에 connector를 인자로 넘겨 실행하면 지갑이 연결되고 context 데이터를 업데이트하고 그중 active 변수를 true로 변경한다.

    deactivate 함수를 실행하면 지갑 연결이 해제되고 active 변수를 false로 변경한다.

     

    import { InjectedConnector } from '@web3-react/injected-connector'
    import { useWeb3React } from "@web3-react/core";
    
    const injected = new InjectedConnector({ supportedChainIds: [1, 3, 4, 5, 42] })
    
    const { activate, deactivate } = useWeb3React();
    
    //✨ 지갑 연결
    const onClickActivate = () => {
        activate(injected, async (error: Error) => {
              /*...에러 처리 코드 생략*/
        });
    };
    
    //✨ 지갑 연결 해제
    const onClickDeactivate = () => {
        deactivate();
    };

     

    📍 connector 연결 시 발생하는 에러 처리

    connector를 연결할 때 다양한 에러가 발생할 수 있는데, 아래와 같이 4가지 경우로 대응할 수 있다.

    1. 지갑이 설치 안되어 있는 경우
    2. 지원하지 않는 네트워크인 경우
    3. 유저가 지갑 연결을 거부한 경우
    4. 그 외

     

     

    import {
      InjectedConnector,
      NoEthereumProviderError,
      UserRejectedRequestError as UserRejectedRequestErrorInjected,
    } from '@web3-react/injected-connector';
    import { UnsupportedChainIdError } from '@web3-react/core';
    
    function getErrorMessage(error: Error) {
      if (error instanceof NoEthereumProviderError) {
        return 'No Ethereum browser extension detected, install MetaMask on desktop or visit from a dApp browser on mobile.'
      } else if (error instanceof UnsupportedChainIdError) {
        return "You're connected to an unsupported network."
      } else if (
        error instanceof UserRejectedRequestErrorInjected
      ) {
        return 'Please authorize this website to access your Ethereum account.'
      } else {
        console.error(error)
        return 'An unknown error occurred. Check the console for more details.'
      }
    }

     

     


     

    DApp을 개발하면서 필수로 알아야 하는 지갑 연동 기능을 web3-react와 함께 구현해봤다.

    이 라이브러리를 굳이 사용하지 않아도 지갑 연동은 할 수 있겠지만, 편리함을 마다하면서까지 각각 모든 지갑 연동 기능을 구현할 필요는 없을 것 같다. 공식 깃허브 docs 폴더에 가면 사용 방법을 자세히 볼 수 있으니까 위에 기재한 기능 외에 다양한 기능을 접해보면 좋을 듯하다.

     

     

     

    Reference.

    https://github.com/NoahZinsmeister/web3-react/tree/v6

    https://codesandbox.io/s/github/NoahZinsmeister/web3-react/tree/v6/example?fontsize=14&hidenavigation=1&theme=dark&file=/pages/index.tsx:1778-2487

    반응형

    댓글