티스토리 뷰

React

[React] MetaMask 연동 (feat. web3)

ljy98 2022. 6. 29. 15:11

오늘은 React를 이용하여 MetaMask와 연동해 볼 것이다.

 

먼저 아래 명령어로 CRA(create-react-app)을 생성하고 web3를 설치한다.

$ npx create-react-app project-name
$ npm i web3

 

src 디렉토리 내에 있는 App.js를 아래와 같이 수정한다.

/* App.js */

import './App.css';
import useWeb3 from './hooks/useWeb3';
import { useEffect, useState } from 'react';

function App() {
    const [account, web3] = useWeb3();
    const [isLogin, setIsLogin] = useState(false);
    const [balance, setBalance] = useState(0);

    const handleSubmit = async (e) => {
        e.preventDefault();
        await web3.eth.sendTransaction({
            from: account,
            to: e.target.receiver.value,
            value: web3.utils.toWei(e.target.amount.value, 'ether'),
        });
    };

    useEffect(() => {
        const init = async () => {
            const balance = await web3?.eth.getBalance(account);
            setBalance(balance / 10 ** 18);
        };
        if (account) setIsLogin(true);
        init();
    }, [account]);

    if (!isLogin) return <div className="App">MetaMask Login First.</div>;
    return (
        <div className="App">
            <div>
                <h2>{account}, welcome!</h2>
                <div>Balance : {balance} ETH</div>
            </div>
            <div>
                <form onSubmit={handleSubmit}>
                    <input type="text" id="receiver" placeholder="receiver" />
                    <input type="number" id="amount" placeholder="amount" />
                    <input type="submit" value="submit" />
                </form>
            </div>
        </div>
    );
}

export default App;

위의 코드를 제대로 테스트하기 위해서는 크롬 등 MetaMask가 설치되어 있는 브라우저를 이용해야 한다.

 

편의상 useWeb3라는 커스텀 hook을 만들어서 코드를 작성했다.

 

handleSubmit()은 암호화폐를 받는 사람의 계정, 받을 금액을 입력하고 submit 버튼을 클릭했을 때 실행되는 함수이다. web3.eth 객체의 내장 함수인 sendTransaction()이 실행되면서 트랜잭션이 발생한다.

 

useEffect()는 account 변수의 값이 바뀔 때 마다 실행된다. init()이 실행되면서 해당 계좌의 balance 값이 balance 변수에 할당되고, account 값이 존재하면 isLogin 값은 false에서 true로 바뀐다.

 

isLogin 값이 false일 때에는 브라우저에 "MetaMask Login First."라는 문구가 나타난다.

 

isLogin 값이 true일 때, 즉 MetaMask 로그인이 된 상태에서는 로그인한 계정, balance가 나오고 암호화폐를 송금할 수 있다.

 

/* src/hooks/useWeb3.js */

import { useEffect, useState } from 'react';
import Web3 from 'web3/dist/web3.min.js';

const useWeb3 = () => {
    const [account, setAccount] = useState(null);
    const [web3, setWeb3] = useState(null);

    const getChainId = async () => {
        const chainId = await window.ethereum.request({
            method: 'eth_chainId',
        });
        return chainId;
    };

    const getRequestAccounts = async () => {
        const account = await window.ethereum.request({
            method: 'eth_requestAccounts',
        });
        return account;
    };

    const addNetwork = async (chainId) => {
        const network = {
            chainId,
            chainName: 'jennyGanache',
            rpcUrls: ['http://127.0.0.1:8545'],
            nativeCurrency: {
                name: 'Ethereum',
                symbol: 'ETH',
                decimals: 18,
            },
        };
        await window.ethereum.request({
            method: 'wallet_addEthereumChain',
            params: [network],
        });
    };

    useEffect(() => {
        const init = async () => {
            try {
                const targetChainId = '0xe36';
                const chainId = await getChainId();
                if (targetChainId !== chainId) addNetwork(targetChainId);
                const [account] = await getRequestAccounts();
                const web3 = new Web3(window.ethereum);
                setAccount(account);
                setWeb3(web3);
            } catch (e) {
                console.error(e.message);
            }
        };
        if (window.ethereum) init();
    }, []);

    return [account, web3];
};

export default useWeb3;

위 코드는 useWeb3 hook에 대한 내용이다.

 

getChainId()와 getRequestAccounts()는 각각 chainId와 계정 정보를 return하는 함수이다.

 

addNetwork()는 인자 값으로 들어가는 chainId에 대한 네트워크를 새로 생성하는 함수이고, 새로 생성되는 블록체인 네트워크의 이름은 jennyGanache라고 설정하였다.

 

useEffect()의 init() 함수를 살펴보겠다. targetChainId 값이 0xe36인데 이 값은 3638이라는 숫자를 16진수로 바꾸어 나타낸 것이다. ganache-cli의 default chainId는 1337인데 아래의 명령어로 바꿀 수 있다.

$ ganache-cli --chainId 3638

위의 명령어를 실행하면 chainId가 3638로 바뀐 상태에서 ganache-cli를 사용할 수 있다.

 

그리고 MetaMask에서도 chainId를 3638로 맞춰주어야 한다.

 

[그림 1] 체인 ID 변경

위 사진처럼 ganache 네트워크의 체인 ID를 3638로 똑같이 맞춰주면 된다.

 

targetChainId와 chainId가 같다는 것은 같은 네트워크 상에 있다는 것을 의미한다. 

 

 

이제 원하는 계정으로 암호화폐를 송금해 보겠다.

 

receiver에는 ganache-cli에서 제공한 임의의 계정을 입력하고, amount는 12 ETH를 입력한 후 submit 버튼을 눌렀다.

 

[그림 2] 송금 완료 후 화면

원래 100 ETH가 있었던 계정에서 12 ETH가 빠져나갔고, 수수료로 0.0004 ETH를 지불한 것을 확인할 수 있다.

'React' 카테고리의 다른 글

[React] CRA 커스터마이징  (0) 2022.06.29
[React] Redux Middleware (redux-thunk, redux-saga)  (0) 2022.05.12
[React] React Router  (0) 2022.05.12
[React] Redux 사용 방법  (0) 2022.05.10
[React] 추가 Hooks (useReducer, useCallback, useMemo)  (0) 2022.05.02
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함