목차
1. 목표
2. 관련 패키지
3. truffle 설치 및 세팅
4. 코드 작성하기
5. 확인하기
사과 가게
1. 목표
- 1 ETH를 이용해서 사과 1개를 산다.
- 내 계정이 가지고 있는 사과의 개수를 보여준다.
- 내가 가진 모든 사과를 한 번에 환불할 수 있다. (CA의 값이 줄고 EOA의 값이 늘어난다.)
2. 관련 패키지
- react
- ganache-cli
- truffle
- web3
3. truffle 설치 및 세팅
$ npx truffle init
truffle-config.js
ganache-cli를 이용해서 로컬환경에서 테스트를 진행하기 위해서 development 주석을 해제한다.
4. 코드 작성하기
$ npx create-react-app front
4-1.App.jsx
import useWeb3 from "./hooks/useWeb3"
import AppleShop from "./pages/appleShop"
const App = () => {
const [account, web3] = useWeb3()
if (!account || !web3) return <> 메타마스크와 연결 후 사용해주세요!</>
return (
<>
<h1> 사과가게 </h1>
<AppleShop web3={web3} account={account} />
</>
)
}
export default App
4-2.hooks/useWeb3.js
import { useEffect, useState } from "react"
import Web3 from "web3"
const useWeb3 = () => {
const [account, setAccount] = useState(null)
const [web3, setWeb3] = useState(null)
const init = async () => {
try {
const [account] = await window.ethereum.request({ method: "eth_requestAccounts" })
const web3 = new Web3(window.ethereum)
setAccount(account)
setWeb3(web3)
} catch (e) {
setAccount(null)
setWeb3(null)
}
}
useEffect(() => {
if (!window.ethereum) return
init()
}, [])
return [account, web3]
}
export default useWeb3
사용자에게 직접 서명을 얻는 것이 아닌 메타마스크에 저장되어 있는 개인키로 서명을 하는 과정을 위해서 브라우저에서 메타마스크에 연동하여 web3를 이용해서 네트워크에 요청한다.
4-3.contract/appleShop.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract AppleShop {
mapping (address=>uint256) public myApple;
function buy() public payable {
myApple[msg.sender] += 1;
}
function get() public view returns(uint256){
return myApple[msg.sender];
}
//전체 환불
function sell() public payable {
uint256 refund = myApple[msg.sender] * 10 ** 18; //1
myApple[msg.sender] = 0;
payable(msg.sender).transfer(refund);
}
}
상태변수 myApple은 어떤 계정이 얼마의 사과를 가지고 있는지 확실하게 알기 위해서 키-값형태로 관리하는 것이 좋다.
payable
스마트 컨트랙트를 작성할 때 함수 부분에 payable 키워드를 작성하게 되면 해당 함수가 'ETH'를 받을 수 있다는 것을 의미한다.
function A () public payable {
// 함수에서 이더를 받을 수 있다.
}
CA계정에서 EOA로 이더를 보낼 때 payable을 작성하여 해당 주소로 이더를 보내줄 수 있다.
payable(msg.sender).transfer(/* 주소가 받을 이더의 양*/)
transfer() 함수는 호출을 하는 CA의 ETH를 msg.sender에게 보내준다.
4-4.migrations/1_deploy_appleShop.js
배포를 위해서 마이그레이션 파일을 작성한다.
const AppleShop = artifacts.require("appleShop")
module.exports = (deployer) => {
deployer.deploy(AppleShop)
}
$ npx truffle migrate
생성된 json파일을 src/contract/AppleShop.json 디렉터리 생성 후 추가 해준다.
4-5.pages/appleShop.jsx
import { useEffect, useState } from "react"
import AppleShopContract from "../contract/AppleShop.json"
const AppleShop = ({ web3, account }) => {
const [deployed, setDeployed] = useState(null)
const [apple, setApple] = useState(0)
const buy = async () => {
await deployed.methods.buy().send({
from: account,
value: web3.utils.toWei("1", "ether"),
})
get()
}
const sell = async () => {
await deployed.methods.sell().send({
from: account,
})
get()
}
const get = async () => {
if (!deployed) return
try {
const apple = await deployed.methods.get().call()
setApple(apple)
} catch (e) {
console.log(e.message)
}
}
useEffect(() => {
get()
}, [deployed])
useEffect(() => {
//CALL
if (!web3) return
const instance = new web3.eth.Contract(AppleShopContract.abi, "0x597d8e20f66c89c1d2b38817f1af3588c7156d8c")
setDeployed(instance)
}, [])
return (
<>
<h2>사과 가격 : 1ETH</h2>
<div>
내가 가진 사과 개수 : {apple}
<button onClick={buy}>사과 구매</button>
</div>
<div>
총 사과 판매 가격 : 1ETH <button onClick={sell}>사과 판매</button>
</div>
</>
)
}
export default AppleShop
5. 확인하기
메타마스크에 가나쉬 네트워크가 연결되어 있지 않다면 화면이 제대로 렌더링 되지 않을 것이다.
메타마스크 설치 및 계정에 연결을 하면 맨 위의 목표에 있었던 화면이 보인다.
사과구매 버튼을 누르면 메타마스크와 연동되어 서명을 포함한 트랜잭션 생성 후 가나쉬 네트워크로 요청 후 블록이 담기면 화면에서 볼 수 있다.
사과판매 버튼을 누르면 내가 보유한 개수를 * 1 ETH만큼을 반환되는 로직이 구현되어 있다.
당연히 스마트 컨트랙트를 배포하거나 send() 함수를 사용하게 되면서 가스 소비가 생기니 맨 처음 잔액보다는 적다!!
'BlockChain' 카테고리의 다른 글
ERC20 표준 메서드 종류 및 역할 (0) | 2023.06.01 |
---|---|
NFT(Non-Fungible Token)의 개념 (0) | 2023.05.31 |
Blockchain - Layer2 (레이어2) (0) | 2023.05.30 |
Solidity (솔리디티) 문법과 Smart Contract 생성자 함수 (2) | 2023.05.27 |
Ethereum - ERC 표준 (0) | 2023.05.27 |