본문 바로가기
블록체인/솔리디티

스마트컨트랙트에 결제 기능 넣기

by 혀닙 2022. 7. 20.

 

 

사과가게 만들기

 

함수의 payable 개념

  • payable 키워드가 있어야만 tx 객체의 to 속성값인 CA 계정으로, value 속성값인 ETH를 줄 수 있다.
  • 즉, tx 객체를 보낼 때, value 속성에 이더를 넣기 위해서 payable를 작성해주어야 한다,

 

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

contract AppleShop{
    mapping(address => uint) myApple;


	//	구매: myApple 변수의 address에 사과 갯수++,
    //	tx 객체 보낼 때 단위당 사과 갯수 만큼 value값을 주기 위해 payable 작성
    function buyApple() public payable {
        myApple[msg.sender]++;
    }

	//  환불: 스마트 컨트랙트에 보관해놓은 모든 돈을 돌려 받는 것과 같은 느낌
    //	해당 계정의 사과 갯수를 0으로 만들고

    function sellApple(uint _applePrice) public payable{
        uint256 refund = myApple[msg.sender] * _applePrice;
        myApple[msg.sender] = 0;
        payable(msg.sender).transfer(refund);
    //	어드레스 타입의 계정에 돈을 보내는 행위를 할 수 있게 하기 위해 
    //	payable(bytes20)의 명시적인 타입 변환 방식을 통해 transfer() 메서드 사용
    }

    function getApple() view public returns(uint){
        return myApple[msg.sender];
    }
}

 

 

프론트 코드 작성

프론트 코드?

counter 만들었던 코드랑 비슷하다.

appleShop의 구매, 환불 버튼 클릭 시 실행되는 온클릭 함수 부분만 눈여겨 보면 된다.

 

//	front/src/hooks/useWeb3.jsx

import { useState, useEffect } from "react";
import Web3 from "web3/dist/web3.min.js";

const useWeb3 = () => {
	const [account, setAccount] = useState();
	const [web3, setWeb3] = useState();

	const getAccount = async () => {
		const [account] = await window.ethereum.request({
			method: "eth_requestAccounts",
		});
		return account;
	};

	useEffect(() => {
		(async () => {
			if (!window.ethereum) return;
			const account = await getAccount();
			const web3 = new Web3(window.ethereum);
			setAccount(account);
			setWeb3(web3);
		})();
	}, []);

	return [web3, account];
};

export default useWeb3;

 

 

// front/app.jsx

import logo from "./logo.svg";
import useWeb3 from "./hooks/useWeb3";
import "./App.css";
import AppleShop from "./components/AppleShop";

function App() {
	const [web3, account] = useWeb3();

	if (!account) return <div> 돌아가 </div>;
	return (
		<div className="App">
			<h2> AppleShop </h2>
			<h3> Account: {account} </h3>
			<AppleShop _web3={web3} _account={account}></AppleShop>
		</div>
	);
}

export default App;

 

 

// front/src/components/AppleShop.jsx

import { useState, useEffect } from "react";
import AppleShopContract from "../contracts/AppleShop.json";

const AppleShop = ({ _account, _web3 }) => {
	const [apple, setApple] = useState(0);
	const [deployed, setDeplyed] = useState();

//바로 이부분. contract 작성 시 함수에 payable를 달아주었기 때문에 tx 객체에 value 값(단위: wei)을 줄 수 있게 되었다.
	const getBuy = async () => {
		await deployed.methods.buyApple().send({
			from: _account,
			to: "0x2B77E2d6B41f693732F507d65791983060dCbfC3",	//CA 계정
			value: _web3.utils.toWei("1", "Ether"),
		});

		const current = await deployed.methods.getApple().call();
		setApple(current);
	};


//마찬가지. contract 작성 시 함수에 payable를 달아주었기 컨트랙트의 함수 내부에서 transfer()메서드 호출이 가능했다.
	const getRefund = async () => {
		const ether = _web3.utils.toWei("1", "ether");
		await deployed.methods.sellApple(ether).send({
			from: _account,
			to: "0x2B77E2d6B41f693732F507d65791983060dCbfC3",	//CA 계정
		});
		const current = await deployed.methods.getApple().call();
		setApple(current);
	};

	useEffect(() => {
		(async () => {
			const { abi } = AppleShopContract;
			const CA = "0x2B77E2d6B41f693732F507d65791983060dCbfC3";

			const instance = await new _web3.eth.Contract(abi, CA);
			const current = await instance.methods.getApple().call();

			setDeplyed(instance);
			setApple(current);
		})();
	}, []);
	return (
		<>
			<h3> 개당 사과 가격: 1ETH </h3>
			<div> 나의 사과 갯수: {apple}</div>
			<button onClick={getBuy}> 구매하기 </button>

			<button onClick={getRefund}> 환불하기 </button>
		</>
	);
};

export default AppleShop;

 

'블록체인 > 솔리디티' 카테고리의 다른 글

ERC20토큰  (0) 2022.07.21
address 타입의 분류: address / address payable  (0) 2022.07.20
솔리디티 문법 실행  (0) 2022.07.11

댓글