728x90
1. 초기 설정
트러플 초기 설정
npx truffle init
가나쉬 실행
npx ganache-cli
리액트 폴더 만들기
npx create-react-app myapp
src 폴더 안에 contracts폴더 생성
truffle-config.js
module.exports = {
contracts_build_directory: "myapp/src/contracts",
networks: {
development: {
host: "127.0.0.1",
port: 8545,
network_id: "*",
},
},
compilers: {
solc: {
version: "0.8.17",
},
},
};
contracts_build_directory : 배포시 빌드되는 폴더를 정해준다.
migrations/2_deploy_AppleShop.js
const AppleShop = artifacts.require("AppleShop");
module.exports = function (deployer) {
deployer.deploy(AppleShop);
};
2. 스마트 컨트랙트
contracts/AppleShop.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract AppleShop{
mapping(address => uint) myApple;
// 사과 구매 함수
function buyApple() public payable {
myApple[msg.sender] += 1;
}
// 사과 전체 판매 함수
function sellApple(uint applePrice) public payable{
uint256 refund = myApple[msg.sender] * applePrice;
myApple[msg.sender] = 0;
payable(msg.sender).transfer(refund);
}
// 가지고 있는 사과 확인 함수
function getApple() view public returns(uint){
return myApple[msg.sender];
}
}
배포
npx truffle migration
3. 프론트
(1) 커스텀 훅
myapp/src/hooks/useWeb3.js
import React, { useEffect, useState } from "react";
import Web3 from "web3/dist/web3.min.js";
const useWeb3 = () => {
const [account, setAccount] = useState();
const [web3, setWeb3] = useState();
const getRequestAccount = async () => {
const [account] = await window.ethereum.request({
method: "eth_requestAccounts",
});
return account;
};
useEffect(() => {
(async () => {
const account = await getRequestAccount();
const web3 = new Web3(window.ethereum);
setAccount(account);
setWeb3(web3);
})();
}, []);
return [web3, account];
};
export default useWeb3;
(2) 컴포넌트
myapp/src/components/AppleShop.js
import React, { useEffect, useState } from "react";
import AppleShopContract from "../contracts/AppleShop.json";
const AppleShop = ({ web3, account }) => {
const [apple, setApple] = useState();
const [deployed, setDeployed] = useState();
const [CA, setCA] = useState();
// 사과 구매하기 버튼 함수
const buy = async () => {
await deployed.methods.buyApple().send({
from: account,
to: CA,
value: web3.utils.toWei("1", "ether"),
});
const currentApple = await deployed.methods.getApple().call();
setApple(currentApple);
};
// 사과 판매하기 버튼 함수
const sell = async () => {
const eth = web3.utils.toWei("1", "ether");
await deployed.methods.sellApple(eth).send({
from: account,
to: CA,
});
const currentApple = await deployed.methods.getApple().call();
setApple(currentApple);
};
useEffect(() => {
(async () => {
if (!web3) return;
const networkId = await web3.eth.net.getId();
const instance = await new web3.eth.Contract(
AppleShopContract.abi,
AppleShopContract.networks[networkId].address
);
// 인스턴스 객체 사과 갯수 가져오는 함수
const currentApple = await instance.methods.getApple().call();
setApple(currentApple);
setDeployed(instance);
setCA(AppleShopContract.networks[networkId].address);
})();
}, []);
return (
<div>
<div>사과 한개 가격 : 1ETH</div>
<div>내가 가지고 있는 사과 : {apple} 개</div>
<button onClick={buy}>구매하기</button>
<div>사과 판매 가격 : {apple} ETH</div>
<button onClick={sell}>사과 전체 판매하기</button>
</div>
);
};
export default AppleShop;
(3) App.js
myapp/src/App.js
import React from "react";
import "./App.css";
import AppleShop from "./components/AppleShop";
import useWeb3 from "./hooks/useWeb3";
function App() {
const [web3, account] = useWeb3();
if (!account) return <h1>메타마스크를 연결해주세요</h1>;
return (
<div className="App">
<h2>사과 앱</h2>
<AppleShop web3={web3} account={account} />
</div>
);
}
export default App;
728x90
'개발 > BlockChain' 카테고리의 다른 글
[BlockChain] ERC20 Token - openzeppelin 사용 (0) | 2022.12.06 |
---|---|
[BlockChain] ERC20 Token 만들기 (0) | 2022.12.06 |
[BlockChain] 스마트컨트랙트로 투표 Dapp 만들기 (0) | 2022.12.06 |
[BlockChain] 메타마스크 토큰추가 (0) | 2022.12.06 |
[BlockChain] ganache, react, express로 메타마스크 연결하기 (0) | 2022.12.05 |