[TIL] Part4 - DAY66 Project - typescript

박동우·2023년 6월 28일

블록체인 스쿨 3기

목록 보기
62/72

[TIL] 2023-06-28 DAY66


Project

GIT 주소
https://github.com/dowoo303/SOLIDITY
https://github.com/dowoo303/hardhat


오늘 배운것들

  1. typescript(0623폴더에 이어서)

각종 팁

회고




💻 Solidity 코딩

✅ typescript

시작

npx create-next-app@latest 0628 입력 후 각정설정(대부분 yes)(테일윈드 설치 할지말지도 결정가능)
npm run dev 로 시작

이미지 경로는 public 폴더부터 시작한다.

src/app 폴더 안에 만드는 폴더 명이 새로운 페이지 경로 이름이다.


✅ Solidity

mint nft와 sale nft 컨트랙트 구현해보기

🟥 코드

nft mint

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.18;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";

contract MintNft is ERC721Enumerable {
    string metadataUri;
    mapping(uint => string) metadataUris;

    uint maxAmount;

    constructor(string memory _name, string memory _symbol, string memory _metadataUri, uint _maxAmount) ERC721(_name, _symbol) {
        metadataUri = _metadataUri;
        maxAmount = _maxAmount;
    }


    function mintNft() public {
        // 수량 제한
        require(totalSupply() < maxAmount, "No more mint.");

        uint tokenId = totalSupply()+1;

        _mint(msg.sender, tokenId);

        metadataUris[tokenId] = metadataUri;
    }

    function tokenURI(uint _tokenId) public override view returns(string memory) {
        // 아래 if문을 활용하여 reveal전 이미지나 데이터를 보여주다가 리빌이 된 후 바뀌는 식으로 구성해도됨
        // 또는 거래가 여러번 이루어진 nft는 이미지나 데이터가 변경된다던가 등등 여기서 모두 작업가능
        // if() {
        //     return "metadata";
        // }

        return string(abi.encodePacked(metadataUri, '/', Strings.toString(_tokenId), '.json'));

        // 만약 위 mapping을 사용한다면
        // return metadataUris[_tokenId];
    }

    // 사용자가 마지막으로 민팅한 NFT 띄워주기
    function getLatestNft(address _nftOwner) public view returns(uint) {
        uint nftLength = balanceOf(_nftOwner);
        uint latestNft = tokenOfOwnerByIndex(_nftOwner, nftLength - 1);

        return latestNft;
    }

    function getAllNft(address _nftOwner) public view returns(uint[] memory) {
        uint nftLength = balanceOf(_nftOwner);

        uint[] memory allNft = new uint[](nftLength);

        for(uint i; i<nftLength; i++) {
            allNft[i] = tokenOfOwnerByIndex(_nftOwner, i);
        }

        return allNft;
    }

}

nft sale

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.18;

import "./230628.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract SaleNft is Ownable {
    // 범용적으로 사용하기 위해서는 오픈재플린에서 ERC721 import
    MintNft mintNftContract;

    constructor(address _mintNftAddress) {
        mintNftContract = MintNft(_mintNftAddress);
    }

    mapping(uint => uint) tokenPrices;
    uint[] public onSaleNft;

    function setSaleNft(uint _tokenId, uint _price) public {
        address nftOwner = mintNftContract.ownerOf(_tokenId);

        require(nftOwner == msg.sender);   // nft 주인 체크
        require(mintNftContract.isApprovedForAll(nftOwner, address(this)));
        require(_price > 0);    // 음수나 0(판매중인 상태가 아닌 상태)방지
        require(tokenPrices[_tokenId] == 0);    // 판매중이 아닌지 확인

        tokenPrices[_tokenId] = _price;
        onSaleNft.push(_tokenId);
    }

    function purchaseNft(uint _tokenId) public payable {
        address nftOwner = mintNftContract.ownerOf(_tokenId);
        uint nftPrice = tokenPrices[_tokenId];

        require(nftOwner != msg.sender);        // 자기자신은 구매 불가
        require(nftPrice > 0);      // 판매중인지 체크
        require(nftPrice <= msg.value);     // 구매할 돈을 충분히 보냈는지 체크

        // 수수료
        uint tradeFee = msg.value / 20;
        
        payable(nftOwner).transfer(msg.value - tradeFee);   // 비용지불
        payable(owner()).transfer(tradeFee);        // 수수료
        mintNftContract.safeTransferFrom(nftOwner, msg.sender, _tokenId);
    }

}

profile
HELLO!

0개의 댓글