[Web3.js] Web3.js와 MetaMask(메타마스크) 연동하기

Web3.js와 MetaMask(메타마스크) 연동하기 Connect Web3.js to MetaMask

아무말

오랜만의 dApp 개발에 기분이 좋아진 인피덕

블로그에도 관련 내용을 남기고 싶어 메타마스크 연동 방법을 포스팅하려고 한다.

본론

Web3.js 와 MetaMask가 설치되어 있다는 가정 하에, 간단한 예제 코드로 설명하고자 한다.

import Web3 from 'web3'
...
return new Promise((resolve, reject) => {
 // 1
  window.addEventListener('load', async () => {
    let web3, account;
    // 2
    if (window.ethereum) {
      web3 = new Web3(window.ethereum);
    // 3
    } else if (typeof window.web3 !== 'undefined') {
      web3 = new Web3(window.web3.currentProvider);
    } else {
      // 4
      reject(new Error('No web3 instance injected, using local web3.'))
    }
    if (web3) {
      // 5
      account = await web3.eth.requestAccounts();
    }
  })
})
  1. 페이지가 load 됐을 때 감지할 수 있도록 event listener를 설정한다.

  2. window.ethereum이 있다(MetaMask가 설치된 상태)면 web3 객체를 주입한다. (MetaMask가 window.ethereum을 제공하고 있다.)

  3. window.web3가 있다(MetaMask가 설치된 상태)면 해당 객체에 속한 currentProvider로 web3 객체를 주입한다.
    • 현재 window.web3는 레거시 코드이고 사용을 지양하고 있지만, 이 내용을 모르는 프로젝트에 경고 메시지를 발생시키기 위해 더미 코드로 남겨둔 상태이다. 즉, window.ethereum으로 연동하는 게 좋다.
  4. window.ethereumwindow.web3가 모두 없는 경우 에러를 발생시킨다.

  5. web3 객체가 있으면 계정 정보를 가져온다.
    • 동일한 의미의 코드들: window.ethereum.enable() (레거시 코드), window.ethereum.request({ method: 'eth_requestAccounts' }) (web3만 사용하는 코드에서는 동작하지 않을 수 있음)

위 코드를 실행시키면 아래와 같은 팝업이 뜨고, 연결을 누르면 web3.js와 MetaMask의 연동이 완료된다.

image_01 image_02

발생할 수 있는 에러

이미 연동 팝업이 뜬 상태에서 다시 연동하려고 할 때

inpage.js:1 MetaMask - RPC Error: Request of type 'wallet_requestPermissions' already pending for origin https://.com. Please wait. {code: -32002, message: "Request of type 'wallet_requestPermissions' alread…origin https://x.com. Please wait."}

이미 띄워진 팝업을 찾아 연동해주면 해결된다.

연동 중인 상태에서 연동을 해제할 때

이 경우는 MetaMask에서 지원하고 있는 이벤트 accountsChanged를 사용하면 된다.

이 이벤트는 계정이 연동됐거나 연동 해제 됐을 때 캐치할 수 있는 이벤트이다.

ethereum.on('accountsChanged', handler: (accounts: Array<string>) => void);

이외에도, MetaMask 연결 성공 및 실패 등의 이벤트가 있으니 필요 시 사용하면 된다.

참고

이 글의 저작권은 Attribution-NonCommercial 4.0 International 라이센스를 따릅니다. Attribution-NonCommercial 4.0 International