BlockChain
(BlockChain) Solidity를 이용한 간단하게 Bakery 예제
JJeongHyun
2023. 3. 8. 20:46
반응형
작업 폴더 생성
- front / back 폴더생성
각 폴더에 필요로 하는 라이브러리 및 init 설정 ( vscode Terminal )
- front
- yarn create react-app front
- cd front
- yarn add web3
- back
- cd back
- npm init -y
- npm i truffle
- npm i -D prettier-plugin-solidity
- npx truffle init
useWeb3.js 생성
- Custom Hook 생성
solidity 파일 생성 ( Bakery.sol )
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
contract Bakery {
mapping(address => uint) public breads;
function buyBread() public payable {
require(msg.value >= 10 ** 18);
breads[msg.sender] += 1;
}
function sellBread() public payable {
breads[msg.sender] -= 1;
payable(msg.sender).transfer(10 ** 18);
}
function getBread() public view returns (uint) {
return breads[msg.sender];
}
function getSender() public view returns (address) {
return msg.sender;
}
}
- CA : Contract Address, 계정이며 지갑 주소 중 하나 이므로 Ether를 보유할 수 있다
- function payable 옵션
- payable은 스마트 컨트랙트에게 거래를 하고 싶으면 쓰는 옵션
- CA주소로 해당 컨트랙의 Balance(잔액)를 확인할 수 있다
migration 내 배포 JS 파일 생성
const Bakery = artifacts.require("Bakery");
module.exports = function (deployer) {
deployer.deploy(Bakery);
};
컴파일 및 배포
- npx truffle compile
- npx truffle migration
front/src내 contract, component 폴더 생성
- 컴파일, 배포 후에 생성된 build내 JSON 형식의 파일을 가져와서 import 할 수 있도록 넣어둔다
App.js/Bakery.jsx
- 현재 빵의 개수를 출력
- contract의 getBread 메서드를 호출
import { useState, useEffect } from "react";
import BakeryContract from "../contracts/Bakery.json";
const Bakery = ({ web3, account }) => {
const [bread, setBread] = useState(0);
const initialize = async () => {
if (!web3) return;
const networkId = await web3.eth.net.getId();
const _CA = BakeryContract.networks[networkId].address;
const abi = BakeryContract.abi;
const _deployed = new web3.eth.Contract(abi, _CA);
const _bread = await _deployed.methods.getBread().call({ from: account });
setBread(_bread);
};
useEffect(() => {
initialize();
}, []);
return <div>현재 빵 개수 : {bread}</div>;
};
export default Bakery;
Bakery.jsx
- buyBread함수 생성 ( 빵을 구매하는 함수 )
- sellBread함수 생성 ( 빵을 판매하는 함수 )
- initialize함수내에 있는 deployed, CA를 가져오기 위해 새롭게 state를 생성해서 정의해 준다
import { useState, useEffect } from "react";
import BakeryContract from "../contracts/Bakery.json";
const Bakery = ({ web3, account }) => {
const [bread, setBread] = useState(0);
const [deployed, setDeployed] = useState();
const [CA, setCA] = useState();
const initialize = async () => {
if (!web3) return;
const networkId = await web3.eth.net.getId();
const _CA = BakeryContract.networks[networkId].address;
setCA(_CA);
const abi = BakeryContract.abi;
const _deployed = new web3.eth.Contract(abi, _CA);
setDeployed(_deployed);
const _bread = await _deployed.methods.getBread().call({ from: account });
setBread(_bread);
};
const buyBread = async () => {
await deployed.methods
.buyBread()
.send({ from: account, to: CA, value: web3.utils.toWel("1") });
const _bread = await deployed.methods.getBread().call({ from: account });
setBread(_bread);
};
const sellBread = async () => {
await deployed.methods.sellBread().send({ from: account });
const _bread = await deployed.methods.getBread().call({ from: account });
setBread(_bread);
};
useEffect(() => {
initialize();
}, []);
return (
<>
<div>현재 빵 개수 : {bread}</div>
<button onClick={buyBread}>빵 사기</button>
<button onClick={sellBread}>빵 팔기</button>
</>
);
};
export default Bakery;
실행 결과 )