1. 프론트와 메타마스크 연결
(1) 네트워크 추가
메타마스크에서 네트워크 수동추가를 누른후 아래와 같이 입력한다.
현재 ganache를 켜놨기 때문에 사용중이라고 뜨지만 상관없다.
계정 가져오기를 누른후 ganache 에 있는 개인키를 입력하면
test넷에 test용 이더가 들어가 있는걸 확인 할 수 있다.
(2) 프론트와 연결
트랜잭션을 보낼때 사용자의 개인키를 사용해서 서명을 만드는 과정을 거친다.
개인키를 이용하면 위와 같이 계정을 불러올수 있기 때문에 서버에 저장하는것은 많이 위험하다.
그래서 서명을 만들기 위해서는 메타마스크와 같은 지갑 프로그램을 이용한다.
프론트에서 메타마스크에 요청
메타마스크가 사용자의 개인키를 이용해 서명을 만들어 트랜잭션 발생시킨 후 블록체인 네트워크로 요청을 보낸다.
응답값을 프론트가 받아서 클라이언트에게 보여준다.
메타마스크는 사용자의 개인키를 이용해서 서명을 만들고 전달받은 데이터와 서명을 합쳐서 블록체인 네트워크로 전달
요청 : 프론트 -> input -> 메타마스크(지갑) -> 블록체인 네트워크
응답 : 블록체인 네트워크 -> 메타마스크(지갑) -> 프론트
그렇기 때문에 프론트서버랑 메타마스크가 서로 요청, 응답을 받을수 있게만 만들어 주면 된다.
(3) 요청,응답 예시
쇼핑몰을 예를 들어 상품들이 등록되어 있고 사용자가 코인이나 토큰으로 구매를 할때
상품 데이터까지 블록체인 네트워크에 저장하면 너무 비효율적이다.
그래서 프론트, 백엔드를 같이 구현해서 상품데이터는 데이터베이스에 저장하고
특정 정보들을 가져올땐 백엔드 서버에 요청해서 가져오는 방식으로 한다.
방법 1 : 프론트에서 메타마스크로 바로 요청을 보내서 트랜잭션을 발생시키는 방법과
방법 2 : 백엔드에서 서명을 제외한 트랜잭션 객체를 만들어서 프론트에 전달하고 받은 객체를 메타마스크로 전달해 서명과 함께 트랜잭션을 보낸다.
방법 3 : 백엔드에서 사용자의 개인키를 가지고 서명을 만들어서 서명까지 포함된 트랜잭션을 블록체인 네트워크로 보낸다.
** 사용자의 개인키로 서명을 만드는건 메타마스크이다.
2. react
(1) /src/hooks/useWeb3.js
web3라이브러리로 계정을 받기 위해 커스텀훅을 만들어준다.
import { useEffect, useState } from "react";
import Web3 from "web3/dist/web3.min.js";
// web3 라이브러리는 nodejs에서 사용하는 라이브러리 기능들이 있어서
// 사용할 최소의 기능만 사용하기위해 프론트에서 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 accounts = await window.ethereum.request({
method: "eth_requestAccounts",
});
console.log(accounts);
return accounts;
};
const addNetwork = async (chainId) => {
// 메타마스크 네트워크 추가할떄 필요한 속성들
const netWork = {
chainId: chainId,
chainName: "Ganache",
rpcUrls: ["http://127.0.0.1:8545"],
nativeCurrency: {
name: "Ethereum",
symbol: "ETH", //통화 단위
deciamls: 18, // 소수점 자리수
},
};
await window.ethereum.request({
method: "wallet_addEthereumChain",
params: [netWork],
});
};
useEffect(() => {
const init = async () => {
try {
const targetChainId = "0x539";
const chainId = await getChainId(); // "1337"를 hex로 변경하면 "0x1e2a"로 변경이 된다.
console.log("체인 아이디", chainId);
if (targetChainId !== chainId) {
// 네트워크를 추가해준다.
addNetwork(targetChainId);
}
const [account] = await getRequestAccounts();
// web3 라이브러리 사용해서 메타마스크에 연경
const web3 = new Web3(window.ethereum);
setAccount(account);
setWeb3(web3);
} catch (e) {
console.log(e);
}
};
if (window.ethereum) {
init();
}
}, []);
return [account, web3];
};
// useWeb3라는 커스텀 훅을 만든거다.
// useEffect나 useState처럼 커스텀 훅을 만들어서 사용하는것
export default useWeb3;
(2) /src/App.js
import "./App.css";
import { useState, useEffect } from "react";
import useWeb3 from "./hooks/useWeb3";
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.received.value,
value: web3.utils.toWei(e.target.amount.value, "ether"),
});
};
useEffect(() => {
const init = async () => {
const balance = await web3?.eth.getBalance(account);
setBalance(balance / 10 ** 10);
};
if (account) setIslogin(true);
init();
}, [account]);
if (!islogin) return <div>메타마스크 로그인 해주세요</div>;
return (
<div className="App">
<div>
<h1>사용자 : {account}</h1>
<div>남은 금액 : {balance}</div>
</div>
<div>
<form onSubmit={handleSubmit}>
<label>받은 계정</label> <br />
<input id="received" type="text" />
<br />
<label>보낼 계정</label>
<br />
<input id="amount" type="number" />
<br />
<button type="submit">전송</button>
</form>
</div>
</div>
);
}
export default App;
(3) 구현 모습
첫 시작시 로그인 요청
로그인 하면 아래와 같이 된다.
'개발 > BlockChain' 카테고리의 다른 글
[BlockChain] solidity 컴파일 (0) | 2022.12.05 |
---|---|
[BlockChain] geth (0) | 2022.11.28 |
[BlockChain] RPC web3 테스트 (0) | 2022.11.21 |
[BlockChain] ubuntu 환경 설정 (0) | 2022.11.21 |
[BlockChain] TypeScript로 transaction 만들기 (0) | 2022.11.15 |