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] 메타마스크 토큰추가 (0) | 2022.12.06 |
[BlockChain] truffle로 스마트컨트랙트 배포하기 (0) | 2022.12.05 |
[BlockChain] 스마트 컨트랙트 배포 (0) | 2022.12.05 |
[BlockChain] solidity 컴파일 (0) | 2022.12.05 |