[BlockChain] ganache, react, express로 메타마스크 연결하기

2022. 12. 5. 22:32·개발/BlockChain
728x90
반응형

1. 초기설정

react 폴더 설치

npx create-react-app front

프론트는 리액트로 구성, 메타마스크 연결은 가나쉬 네트워크에 연결, 스마트컨트랙트 배포는 트러플로 구성했다.

 

가나쉬 실행

npx ganache-cli

트러플 초기 설정

npx truffle init

 

리액트폴더안에서 라이브러리 설치

npm i axios web3

2. 스마트 컨트랙트

/contracts/Counter.sol

// SPDX-License-Identifier:MIT
pragma solidity ^0.8.17;

contract Counter{
    uint256 private _count;
    event Count(uint256 count);
    
    function current() public view returns(uint256){
        return _count;
    }
    function increment() public {
        _count += 1;
        emit Count(_count);
    }
    function decrement() public {
        _count -= 1;
    }
}

3. truffle-config.js

module.exports = {
  networks: {
    development: {
      host: "127.0.0.1",
      // 포트는 가나쉬 포트로
      port: 8545,
      network_id: "*",
    },
  },
  mocha: {},

  compilers: {
    solc: {
      version: "0.8.17",
    },
  },
};

4. 배포 코드

/migrations/2_deploy_Counter.js

const Counter = artifacts.require("Counter");

module.exports = function (deployer) {
  deployer.deploy(Counter);
};

5. 프론트

(1) 커스텀 훅

/src/hooks/useWeb3.js

import React, { useEffect, useState } from "react";
import Web3 from "web3/dist/web3.min";
const useWeb3 = () => {
  const [account, setAccount] = useState(null);
  const [web3, setWeb3] = useState(null);
  useEffect(() => {
    (async () => {
      if (!window.ethereum) return;
      // 연결되어 있는 계정 가져오기
      const [address] = await window.ethereum.request({
        method: "eth_requestAccounts",
      });
      setAccount(address);
      const web3 = new Web3(window.ethereum);
      setWeb3(web3);
    })();
  }, []);
  return [web3, account];
};

export default useWeb3;

(2) 컴포넌트

/src/somponents/Counter.js

import React, { useEffect, useState } from "react";
import CounterContract from "../contracts/Counter.json";
import axios from "axios";
const Counter = ({ web3, account }) => {
  const [count, setCount] = useState(0);
  const [deployed, setDeployed] = useState(null);
  const increment = async () => {
    const res = await axios.post("http://localhost:4000/api/increment", {
      from: account,
    });

    // 백엔드에서 넘어온 트랜잭션 객체로 트랜잭션 발생
    await web3.eth.sendTransaction(res.data);
  };
  const decrement = async () => {
    const result = await deployed.methods.decrement().send({ from: account });
    if (!result) return;
    const current = await deployed.methods.current().call();
    setCount(current);
  };

  useEffect(() => {
    (async () => {
      if (deployed) return;
      // abi CA 가져오기
      const networkId = await web3.eth.net.getId();
      const CA = CounterContract.networks[networkId].address;
      const { abi } = CounterContract;

      // 컨트랙트 호출
      const Deployed = new web3.eth.Contract(abi, CA);
      const count = await Deployed.methods.current().call();

      // 이벤트 연결
      web3.eth.subscribe("logs", { address: CA }).on("data", (log) => {
        const params = [{ type: "uint256", name: "count" }];
        const value = web3.eth.abi.decodeLog(params, log.data);
        setCount(value.count);
      });

      setCount(count);
      setDeployed(Deployed);
    })();
  }, []);
  return (
    <div>
      <h1>개수 : {count}</h1>
      <button onClick={increment}>+</button>
      <button onClick={decrement}>-</button>
    </div>
  );
};

export default Counter;

(3) App.js

/src/App.js

import "./App.css";
import useWeb3 from "./hooks/useWeb3";
import Counter from "./components/Counter";

function App() {
  const [web3, account] = useWeb3();
  if (!account) return <h1> 메타마스크 연결 해주세요</h1>;
  return (
    <div className="App">
      <h2>계정 : {account}</h2>
      <Counter web3={web3} account={account} />
    </div>
  );
}

export default App;

6. 백엔드

백엔드 폴더를 따로 만든다.

npm i web3 express

/back/app.js

const express = require("express");
const app = express();
const cors = require("cors");
const Web3 = require("web3");
const web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:8545"));
const CounterContract = require("./Counter.json");

app.use(
  cors({
    origin: true,
    credentials: true,
  })
);

app.use(express.json());
app.post("/api/increment", async (req, res) => {
  const { from } = req.body;
  const nonce = await web3.eth.getTransactionCount(from);
  const networkId = await web3.eth.net.getId();
  const CA = CounterContract.networks[networkId].address;
  const abi = CounterContract.abi;
  const deployed = new web3.eth.Contract(abi, CA);
  const data = await deployed.methods.increment().encodeABI();

  let txObject = {
    nonce,
    from,
    to: CA,
    data,
  };
  res.json(txObject);
});

app.listen(4000, () => {
  console.log("4000번 포트 실행");
});

프론트에서 컨트랙트 배포 후 생기는 json객체를 복사하여 back에도 추가해줄것이다.

7. 배포

(1) ganache 실행

npx ganache-cli

(2) 배포

react루트 폴터로 경로이동

npx truffle migration

배포 후 백엔드폴더에도 컴파일된json 객체를 복붙

프론트, 백엔드 서버키고 확인

728x90
반응형

'개발 > BlockChain' 카테고리의 다른 글

[BlockChain] 스마트컨트랙트로 투표 Dapp 만들기  (0) 2022.12.06
[BlockChain] 메타마스크 토큰추가  (1) 2022.12.06
[BlockChain] truffle로 스마트컨트랙트 배포하기  (1) 2022.12.05
[BlockChain] 스마트 컨트랙트 배포  (0) 2022.12.05
[BlockChain] solidity 컴파일  (1) 2022.12.05
'개발/BlockChain' 카테고리의 다른 글
  • [BlockChain] 스마트컨트랙트로 투표 Dapp 만들기
  • [BlockChain] 메타마스크 토큰추가
  • [BlockChain] truffle로 스마트컨트랙트 배포하기
  • [BlockChain] 스마트 컨트랙트 배포
TeTedo.
TeTedo.
  • TeTedo.
    TeTedo 개발 일기
    TeTedo.
  • 전체
    오늘
    어제
    • 분류 전체보기 (319)
      • 개발 (274)
        • Article (4)
        • 정리 (21)
        • Spring Boot (17)
        • JPA (2)
        • JAVA (6)
        • Database (4)
        • 자료구조 (11)
        • 알고리즘 (32)
        • React (20)
        • Docker (10)
        • node.js (18)
        • Devops (11)
        • Linux (4)
        • TypeScript (3)
        • Go (10)
        • HyperLedger (4)
        • BlockChain (43)
        • html, css, js (48)
        • CS (3)
        • AWS (3)
      • 모아두고 나중에 쓰기 (3)
      • 팀프로젝트 (18)
        • SNS(키보드워리어) (9)
        • close_sea (9)
      • 개인프로젝트 (1)
        • Around Flavor (1)
        • CHAM (13)
        • ethFruitShop (5)
      • 독서 (0)
        • 스프링부트와 AWS로 혼자 구현하는 웹 서비스 (0)
  • 블로그 메뉴

    • 홈
    • 개발일기
    • CS
    • 실습
    • 코딩테스트
    • 웹
    • Go
    • node.js
    • 팀플
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    블록체인
    node.js
    React
    node
    30일챌린지
    mysql
    프로그래머스
    nodejs
    html
    도커
    CSS
    컨테이너
    하이퍼레저
    go언어
    js
    go
    명령어
    30일 챌린지
    erc20
    ERC721
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
TeTedo.
[BlockChain] ganache, react, express로 메타마스크 연결하기
상단으로

티스토리툴바