본문 바로가기
프로그래밍/typescsript

[220629]

by 한코코 2022. 7. 6.

* 메타마스크가 브라우저에 설치되어 있는 상태에서 작업 *

 

 

window.ethereum

 

 

$ npx create-react-app front

 

제네시스 블럭이 같아도 chainID가 다르면 다른 네트워크로 넘어간다.

제네시스 블럭과 chainID값이 같아야 온전히 같은 블록임.

이더리움 네트워크 상에서 고유한 식별자 역할을 함

chainId는 5글자 안 숫자로.

$ $ npm install -g ganache-cli
$ ganache-cli --chainId 7722

 

//useWeb3.js
import { useEffect, useState } from "react";

const useWeb3 = () => {
  useEffect(()=>{
    console.log(window.ethereum)
  })
  return null
};

export default useWeb3;

 

import { useEffect, useState } from "react";

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

  useEffect(() => {
    console.log(window.ethereum)
    // null이 아니면 메타마스크가 설치된 사람
    
    if(window.ethereum) {
    }
  });
  return [account]
};

export default useWeb3;

 

 

프런트에서 메타마스크에 있는 정보를 가져옴.

메타마스크에 연결되어있는 네트워크 정보 -> 0x3

import { useEffect, useState } from "react";

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

  useEffect(() => {
    console.log(window.ethereum)
    // null이 아니면 메타마스크가 설치된 사람
    
    // http에서 받는거라 promise로 반환됨 -> axios를 사용하고있으니까
    if(window.ethereum) {
      window.ethereum.request({
        method:'eth_chainId',
      })
      .then(data =>{
        console.log(data)
      })
    }
  });
  return [account]
};

export default useWeb3;

 

 

 

 

 

 

 

account 정보 가져오기

window.ethereum.request({
	method:'eth_requestAccounts'
})
.then(data=>{
	console.log(data)
})

 

 

import { useEffect, useState } from "react";

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

  // http에서 받는거라 promise로 반환됨 -> axios를 사용하고있으니까
  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
  };

  useEffect(() => {
    const init = async () => {
      try {
        const chainId = await getChainId();
        const account = await getRequestAccounts();
        setAccount(account)
      } catch (e) {
        console.error(e.message);
      }
    };

    if (window.ethereum) {
      init();
    }
  }, []);
  return [account]
};

export default useWeb3;
import useWeb3 from "./hooks/useWeb3";
import {useEffect, useState} from "react"

function App() {
  const [account] = useWeb3()
  const [isLogin, setIsLogin] = useState(false)

  useEffect(()=>{
    if(account) setIsLogin(true)
  },[account])

  if(!isLogin) return <div>메타마스크 로그인 후 사용해주세요</div>
  return <div className="App">Hello React</div>;
}

export default App;

 

 

 

web3 설치시 생기는 오류 해결법

1. 다른 라이브러리를 설치하는 방법

import Web3 from 'web3/dist/web3.min.js'
// web3 -> nodeJSd에서 사용하는 라이브러리라서 번들링안됨 -> 에러뜸
// 해결방법 : web3/dist/web3.min.js

 

2. 웹팩을 건드리는 방법

// 방법 1
ejest

// 방법 2
override : 일반적인 방법
  // override를 사용하는 여러 방법 중에 하나
  $ npm install react-app-rewired
  
  // package.json -> start
    // reat-script -> react-app-rewired start로 바꿔주기
    // override 먼저 읽고, 파일을 읽고, 파일 위에 덮어씌무면서 실행됨
    $ npm install customize-cra
    $ npm install http-browserify
    
    // config.overrides.js 생성

    ```javascript
      const {override} = require('customize-cra')

      module.exports = override(config => {
        config.resolve={
          fallback:{
            ...config.resolve.fallback,
            https: require.resolve('http-browserify')
          }
        }
        return config
      })
    ```
    
  $ npm run start

 

 

 

 

 

 

 

새로운 문법

const a = {
    b:'a',
    c:{}
  }
  a.c?.d == null일경우 undefined으로 바꿔줌 --> 새로운 문법
import { useEffect, useState } from "react";
import Web3 from 'web3/dist/web3.min.js'
// web3 -> nodeJSd에서 사용하는 라이브러리라서 번들링안됨 -> 에러뜸
// 해결방법 : web3/dist/web3.min.js

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

  // http에서 받는거라 promise로 반환됨 -> axios를 사용하고있으니까
  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
  };

  useEffect(() => {
    const init = async () => {
      try {
        const chainId = await getChainId();
        const [account] = await getRequestAccounts(); // 결과물을 배열에 담아주기때문

        // 메타마스크에 요청보내기 -> 메타마스크가 만든 객체가 window.ethereum 이니까 가능
        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;
import useWeb3 from "./hooks/useWeb3";
import { useEffect, useState } from "react";
import { Web3 } from "web3/dist/web3.min";

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

  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>메타마스크 로그인 후 사용해주세요</div>;
  return (
    <div>
      <div>
        <h2>{account}님 환영합니다</h2>
        <div>Balance : {balance} ETH</div>
      </div>
    </div>
  );
}

export default App;

 

 

 

새로 생긴 기능

메인넷에 들어가더라도 사용해야할 네트워크에 접속하게 하는 방법

import { useEffect, useState } from "react";
import Web3 from "web3/dist/web3.min.js";
// web3 -> nodeJSd에서 사용하는 라이브러리라서 번들링안됨 -> 에러뜸
// 해결방법 : web3/dist/web3.min.js

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

  // http에서 받는거라 promise로 반환됨 -> axios를 사용하고있으니까
  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: chainId,
      chainName: "ingGanache",
      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 = "0x1e2a";
        const chainId = await getChainId(); //7722
        // 현재 너의 메타마스크의 체인아이디가 7722니?  0x1e2a
        console.log("너의 체인아이디 : ", chainId);
        if (targetChainId !== chainId) {
          // 네트워크 추가 코드
          addNetwork(targetChainId);
        }
        const [account] = await getRequestAccounts(); // 결과물을 배열에 담아주기때문

        // 메타마스크에 요청보내기 -> 메타마스크가 만든 객체가 window.ethereum 이니까 가능
        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;
import useWeb3 from "./hooks/useWeb3";
import { useEffect, useState } from "react";
import { Web3 } from "web3/dist/web3.min";

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

  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>메타마스크 로그인 후 사용해주세요</div>;
  return (
    <div>
      <div>
        <h2>{account}님 환영합니다</h2>
        <div>Balance : {balance} ETH</div>
      </div>
    </div>
  );
}

export default App;

 

 

 

 

 

 

 

 

거래를 할 수 있게 메타마스크와 연결하기

import { useEffect, useState } from "react";
import Web3 from "web3/dist/web3.min.js";
// web3 -> nodeJSd에서 사용하는 라이브러리라서 번들링안됨 -> 에러뜸
// 해결방법 : web3/dist/web3.min.js

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

  // http에서 받는거라 promise로 반환됨 -> axios를 사용하고있으니까
  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: chainId,
      chainName: "ingGanache",
      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 = "0x1e2a";
        const chainId = await getChainId(); //7722
        // 현재 너의 메타마스크의 체인아이디가 7722니?  0x1e2a
        console.log("너의 체인아이디 : ", chainId);
        if (targetChainId !== chainId) {
          // 네트워크 추가 코드
          addNetwork(targetChainId);
        }
        const [account] = await getRequestAccounts(); // 결과물을 배열에 담아주기때문

        // 메타마스크에 요청보내기 -> 메타마스크가 만든 객체가 window.ethereum 이니까 가능
        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;
import useWeb3 from "./hooks/useWeb3";
import { useEffect, useState } from "react";
import { Web3 } from "web3/dist/web3.min";

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

  const handleSubmit = async (e) => {
    e.preventDefault();

    // 메타마스크한테 sendTransaction을 실행할거야
    await web3.eth.sendTransaction({
      from: account,
      to: e.target.recived.value,
      value: web3.utils.toWei(e.target.amount.value,'ether'),
      // ether단위 숫자를 -> wei 단위로 바꾸는 함수
    });
  };

  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>메타마스크 로그인 후 사용해주세요</div>;
  return (
    <div>
      <div>
        <h2>{account}님 환영합니다</h2>
        <div>Balance : {balance} ETH</div>
      </div>
      <div>
        <form onSubmit={handleSubmit}>
          <input type="text" id="recived" placeholder="받을 계정" />
          <input type="number" id="amount" placeholder="보낼 금액" />
          <input type="submit" value="전송" />
        </form>
      </div>
    </div>
  );
}

export default App;

 

댓글