[MetaMask/Web3.js] wallet_switchEthereumChain으로 MetaMask(메타마스크)에서 네트워크 전환하기

wallet_switchEthereumChain으로 MetaMask(메타마스크)에서 네트워크 전환하기

Using wallet_switchEthereumChain to switch network on Metamask

TL;DR

MetaMask(메타마스크)에서 네트워크를 전환하려면 wallet_switchEthereumChain 메소드를 사용하면 된다.

...
await window.ethereum.request({
  method: "wallet_switchEthereumChain",
  params: [{ chainId: "변경할 chain id", }],
});
...

만약 MetaMask 네트워크 목록에 없는 네트워크로 전환하고자 한다면,

먼저 네트워크를 추가 (wallet_addEthereumChain 메소드 사용) 한 뒤 원하는 네트워크로 전환하면 된다.

wallet_addEthereumChain parameter interface

...
await window.ethereum.request({
  method: "wallet_addEthereumChain",
  params: [metaTestMetaData],
});
...

오늘의 서론 (이라고 적고 현실은 아무말 대잔치)

메타마스크를 무사히 연동한 인피덕

개발하다 보니 각각의 네트워크(메인넷, 테스트넷 등등…)에서 테스트를 해야하는 상황이 발생하는데..

메타마스크 인터페이스에서 일일히 바꿔주며 테스트를 진행하다 보니 좀 귀찮기도 하고..(ㅎ_ㅎ)

컨트랙트를 호출할 때 올바른 네트워크로 스무스하게 변경해줄 수 있으면 좋겠다라는 생각이 들어 찾아보기로 했다.

그러던 중 메타마스크에서(!!) 네트워크 전환 메소드를 지원해준 다는 내용(!!!!!)을 보고 감동을 받아 블로그에 정리해 보고자 한다.

갓타마스크..

본론

아래 설명할 메소드들은 MetaMask에서 지원하는 메소드이기 때문에 반드시 무조건 MetaMask가 있어야 동작한다.

예제 코드를 통해 살펴보도록 하자.

MetaMask 연동 확인

이전 포스팅에 조금 더 자세히 설명되어 있다.

MetaMask가 설치되어 있는지 확인하려면 window.ethereum 으로 확인하면 된다.

// MetaMask가 설치되지 않은 경우, 해당 에러 콘솔이 찍힌다.
if (!window.ethereum) {
  console.error("MetaMask is not found!");
}

MetaMask가 올바른 네트워크에 있는지 확인

여기서 올바른 네트워크란, dApp에서 사용되는 네트워크를 말한다.

예를 들어, infiduk 이라는 dApp이 있다고 가정해 보자. infidukinfiduk chain 위에서 돌아가는 dApp이라고 할 때, 사용자가 infiduk2 chain 위에 있으면 infiduk 에서 사용하는 네트워크가 아니기 때문에 이슈가 발생한다.

따라서, 사용자는 infiduk chain 으로 변경해야 컨트랙트를 호출할 수 있고 이 예시에서는 infiduk chain이 올바른 네트워크가 된다.

// 현재 연결되어 있는 네트워크의 chain id
const chainId = await window.ethereum.request({ method: "eth_chainId" });
// dApp에서 사용하는 네트워크의 chain id
// 예시를 위해 메타디움 테스트 네트워크의 chain id를 사용했다.
const metaTestChainId = "0xC";

// 현재 연결되어 있는 네트워크의 chain id와 dApp에서 사용하는 네트워크의 chain id가 같은지 확인한다.
if (chainId === metaTestChainId) {
  console.log("You are on the correct network!");
} else {
  console.error("You are on the wrong network!");
}

다른 네트워크의 chain id가 궁금하다면 Chainlist에서 찾아보면 된다.

MetaMask의 네트워크를 올바른 네트워크로 바꾸기

wallet_switchEthereumChain 메소드는 EIP-3326 부터 지원한다.

MetaMask에서 지원하는 wallet_switchEthereumChain 메소드로 네트워크를 변경한다.

try {
  // return 값이 null일 경우 해당 요청은 성공적으로 보내진 것이다.
  await window.ethereum.request({
    method: "wallet_switchEthereumChain",
    params: [{ chainId: metaTestChainId }],
  });
  // return 값이 error 객체일 경우 해당 요청은 실패한 요청이다.
} catch (e) {
  // MetaMask에 해당 네트워크가 없는 경우 발생하는 에러
  if (e.code === 4902) {
    console.error("This network is not found in your network!");
    // 다른 이유로 네트워크를 변경하지 못했을 때 처리
  } else {
    console.error("Failed to switch this network");
  }
}

아래 코드는 wallet_switchEthereumChain 의 parameter interface를 정의한 것이다.

interface SwitchEthereumChainParameter {
  chainId: string; // 16진수로 표현되는 ID ex) 0xC
}

위의 코드를 실행하게 되면 아래와 같은 MetaMask 팝업이 나타나고, 네트워크 전환 버튼을 클릭한 후 조금 기다리면 parameter로 넣었던 chainId 의 네트워크로 변경된 것을 확인할 수 있다.

image_01 image_02

여기서 잠깐! 만약 MetaMask UI가 나타나지 않고 코드가 4902 인 에러가 발생했다면 아래 내용을 확인해 보면 된다.

ERROR CODE: 4902 발생 원인

이 에러는 window.ethereum 으로 가져온 MetaMask 네트워크 목록에 wallet_switchEthereumChain 메소드의 parameter로 받은 chainId 와 같은 Id를 갖는 네트워크가 없어서 발생한다.

// MetaMask Error Message
inpage.js:1 MetaMask - RPC Error: Unrecognized chain ID "0xC". Try adding the chain using wallet_addEthereumChain first.

ERROR CODE: 4902 해결 방법

wallet_addEthereumChain 메소드는 EIP-3085 부터 지원한다.

MetaMask에서 지원하는 wallet_addEthereumChain 메소드로 네트워크를 추가한다.

// 예시를 위해 메타디움 테스트 네트워크의 meta data를 사용했다.
const metaTestMetaData = {
	chainId: "0xC"
	chainName: "Metadium Testnet"
	rpcUrls: ["https://api.metadium.com/dev"],
	blockExplorerUrls: ["https://testnetexplorer.metadium.com"],
	nativeCurrency: {
		name: "META",
		decimals: 18,
		symbol: "META"
	},
};

try {
	// return 값이 null일 경우 해당 요청은 성공적으로 보내진 것이다.
	await window.ethereum.request({
		method: "wallet_addEthereumChain",
		params: [metaTestMetaData]
	});
// return 값이 error 객체일 경우 해당 요청은 실패한 요청이다.
} catch (e) {
	console.error("Failed to add network!");
}

아래 코드는 wallet_addEthereumChain 의 parameter interface를 정의한 것이다.

// MetaMask에 추가되는 chain의 meta data
interface AddEthereumChainParameter {
  chainId: string; // 16진수로 표현되는 ID ex) 0xC
  chainName: string;
  nativeCurrency: {
    name: string,
    symbol: string, // 2 ~ 6글자
    decimals: 18,
  };
  // rpcUrls와 blockExplorerUrls의 경우 필수로 하나 이상의 값을 받는다.
  // 배열에 여러 값을 넣어도 첫 번째 값만 사용된다.
  rpcUrls: string[];
  blockExplorerUrls?: string[];
  // interface에 정의되어 있으나 현재는 무시되는 값이다.
  iconUrls?: string[];
}

코드를 실행하면 아래와 같이 네트워크를 추가할 건지 여부를 묻는 MetaMask 팝업이 나타나고,

모든 세부 정보 보기를 클릭하면 코드 상으로 입력한 Metadium Testnet의 meta data가 나타나는 것을 확인할 수 있다.

네트워크 추가가 완료됐다면 위에서 wallet_switchEthereumChain 메소드를 사용했을 때와 동일한 팝업(추가한 네트워크로 전환할 건지 여부를 묻는 MetaMask 팝업)이 나타난다.

image_03 image_04

완료!

결론

블록체인 교육을 받은 지도 어언 3년의 세월이 흐르고.. 세월이 흐른 만큼 MetaMask is GoOD

참고

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