스마트 컨트랙트 - 과일가게

오미희·2021년 10월 17일
0

blockchain

목록 보기
6/13

스마트 컨트랙트 기본세팅
// 위의 작업 이후 이어짐

구매관련 스마트 컨트랙트 작성

진행과정

1. contract파일 생성

// 현재 경로 : 최상위폴더/contracs
// Fruitshop.sol파일 생성

// Fruitshop.sol파일 내용
pragma solidity >=0.4.22 <0.9.0;

contract Fruitshop {
  mapping(address=>uint) myApple;
  constructor () public {
  }
  
  function buyApple() payable external{
    myApple[msg.sender]++; 
  }

  function getMyApple() public view returns(uint){
    return myApple[msg.sender];
  }
  
  function sellApple(uint _applePrice) payable external {
    uint totalPrice = (myApple[msg.sender] * _applePrice);
    myApple[msg.sender] = 0;
    msg.sender.transfer(totalPrice);
  }
}

2. migration폴더에 배포를 위한 파일생성

1) 터미널에 명령어 입력 >> truffle create migration Fruitshop

// migration폴더 안에 Fruitshop관련 배포를 위한 파일을 생성하겠다는 의미

2) 파일 생성 후 안에 내용 추가 필요

//기존 내용
module.exports = function(_deployer) {
  // Use deployer to state migration tasks.
};
-------------------------------------------------------------------------------
// 추가된 내용
var Fruitshop = artifacts.require("./Fruitshop.sol");
// 이는 contract폴더에 생성한 파일을 가져오는 것임.

module.exports = function(_deployer) {
  _deployer.deploy(Fruitshop);
};

3.컴파일과 배포

1) 기존에 client-src-contracts폴더 안 파일 삭제

-- 기존에 client-src-contracts해당 경로의 폴더 내에 파일이 존재시에는 파일들 삭제 후
// 현 경로 최상위폴더
-- 터미널에 입력
>> truffle compile
>> truffle migrate

3. App.js 내용 수정

import React, {useState, useEffect,useReducer } from "react";
import FruitshopContract from "./contracts/Fruitshop.json";
// SimpleStorage.json은 컴파일하면 생성되는 파일로 abi,bin파일에 대한 내용이 합쳐져서 담겨있다.
import getWeb3 from "./getWeb3";
// promise 객체로 되어있다.  -> async await로 가져와야함

import "./App.css";

const App = () => {
  const [myApple,setMyApple] = useState(0);
  let initialState = {web3:null,instance:null,account:null}
  const [state,dispatch] = useReducer(reducer,initialState)

  function reducer(state,action) {
    switch(action.type){
      case "INIT":
        let {web3,instance,account} = action
        return{
          ...state,
          web3,
          instance,
          account
        }
    }
  }

  const buyApple = async () => {
    let {instance,account} = state;
    await instance.buyApple({
      from:account,
      value:10000000000000000000,
      gas:90000,
    })
    setMyApple(prev=>prev+1)
  }
  
  const sellApple = async () => {
    let {instance, account,web3} = state
    await instance.sellApple(web3.utils.toWei("10","ether"),{
      //web3.utils.toWei --> wei 단위로 바꾸어줌
      // toWei의 인자값
      	// 첫번째 ==> 내가 보낼 이더
        // 두번째 ==> 단위
      from:account,
      gas:90000
    })
  }
  
  
  const getApple = async (instance) => {
    if(instance == null) return
    let result = await instance.getMyApple();
    setMyApple(result.toNumber())
  }
  
  const getweb = async () => {
    const contract = require('@truffle/contract');
    // require는 가능한 사용하지 않는 게 좋음
    // 특히나 함수 밖에서 사용시 오류 발생 가능성 매우 높음
    let web3 = await getWeb3();
    let fruitshop = contract(FruitshopContract);
    fruitshop.setProvider(web3.currentProvider);

    let instance = await fruitshop.deployed();
    let accounts = await web3.eth.getAccounts();
    // 계정가져오기 
    // web3를 통해 metamask에 있는 주소 가져오기 가능

    console.log(accounts)

    let InitActions = {
      type:"INIT",
      web3,
      instance,
      account:accounts[0]
    }
    dispatch(InitActions);
    // reducer를 이용해서 web과 instance, account값 상태에 저장.
    getApple(instance)
    // 함수의 마지막 시점에서 현재 내가고 있는 사과 리턴해줌.
    // 즉 페이지가 로드(렌더링)되는 시점에서 현재 내가 가진 사과 리턴해줌.
  }
      /*reducer 내용
      let initialState = {web3:null,instance:null,account:null}
      const [state,dispatch] = useReducer(reducer,initialState);

      function reducer(state,action){
        switch(action.type){
          case "INIT":
            let {web3,instance,account} = action
            return{
              ...state,
              web3,
              instance,
              account
            }
        }
      }
    */

  useEffect(()=>{
    getweb()
  },[])
  // useEffect를 사용하여 페이지 완료시 요청을 한 번 보내고 결과물을 화면에 띄어줌
  
  return(
    <div>
      <h1>사과가격 : 10ETH</h1>
      <button onClick={()=>buyApple()}>Buy</button>
      {/*함수 호출은 함수에 담아서 바로 함수가 실행되는 것을 막음 */}
      <p>내가 가진 사과 : {myApple}</p>
      <button onClick={()=>sellApple()}>Sell(판매가격은:{myApple*10}ETH)</button>
    </div>
  )
}
export default App;

4. 터미널에서 리엑트 실행

>>npm run start
//이렇게 하고 오류남
// 원인 : '@truffle/contract' 를 설치해주지 않아서 반드시 설치해주어야함

profile
안녕하세요

0개의 댓글