본문 바로가기
블록체인/WEB3 개발

NFT 거래소를 위한 스마트 컨트랙트 개발

by 제이제이_은재 2022. 8. 10.
반응형

1. mintNFT

function mintNFT(address recipient, string memory tokenURI) public onlyOwner returns (uint256) {
    _tokenIds.increment();

    uint256 newItemId = _tokenIds.current();
    _mint(recipient, newItemId);
    _setTokenURI(newItemId, tokenURI);
    return newItemId;
}

 

✓ 제대로 작동하는지 확인

 

MintNFT 함수를 이용해 NFT를 민팅한다.

 

민팅한 NFT 잘 출력되는 거 확인.

 

 

2. listUserNFTs

// owner가 보유하고 있는 NFT List
function listUserNFTs(address owner) external view returns (uint[] memory) {

    uint balance = balanceOf(owner);
    uint[] memory tokens = new uint[](balance);
    for (uint i=0; i < balance; i++) {
        tokens[i] = (tokenOfOwnerByIndex(owner, i));
    }

    return tokens;
}

 

✓ 제대로 작동하는지 확인

 

1번에서 생성된 NFT가 잘 조회됨.

 

이미지 하나 더 민팅 후 listUserNFTs 실행하니 2개가 실행되는 거까지 확인

 

 

3. getNftTokens

function getNftTokens(address _nftTokenOwner) view public returns (NftTokenData[] memory) {

        // balanceOf 를 이용해서 해당 owner가 몇 개의 nft를 보유하고 있는지 보여줌. 
        uint256 balanceLength = balanceOf(_nftTokenOwner);

        NftTokenData[] memory nftTokenData = new NftTokenData[](balanceLength);

        for(uint256 i = 0; i < balanceLength; i++) {
            uint256 nftTokenId = tokenOfOwnerByIndex(_nftTokenOwner, i);
            string memory nftTokenURI = tokenURI(nftTokenId);   
            uint tokenPrice = getNftTokenPrice(nftTokenId);
            nftTokenData[i] = NftTokenData(nftTokenId , nftTokenURI, tokenPrice );
        }

        return nftTokenData;

    }

사실상 listUserNFTs와 비슷한 기능. 입력한 주소가 가지고 있는 NFT의 조금 더 디테일한 내용을 보여준다.

이미지의 주소가 연달아나와 가독성은 떨어지지만 링크 3개가 제대로 출력된 모습 확인.

 

4.  addToMarket

function addToMarket(uint256 _tokenId, uint256 _price) public {

        // nft를 소유한 계정에서만 판매등록 가능
        address nftTokenOwner = ownerOf(_tokenId);

        // 마켓에 올리기 위한 조건들
        require(nftTokenOwner == msg.sender, "Caller is not nft token owner.");
        require(_price > 0, "Price is zero or lower.");
        require(nftTokenPrices[_tokenId] == 0, "This nft token is already on sale.");
        require(isApprovedForAll(nftTokenOwner, address(this)), "nft token owner did not approve token.");

        nftTokenPrices[_tokenId] = _price;
        // push를 이용해 데이터를 넣어줌
        onSaleNftTokenArray.push(_tokenId); //판매중인 nft list
}

 

마켓에 올리려고 실행을 해보면 이러한 에러가 나오는 것을 확인할 수 있음. 

setApprovalForAll 함수를 이용해 approved를 해야 마켓에 올릴 수 있다.

approve 실행 후 다시 마켓에 등록.

 

4.  getMarketList

// 판매리스트, 배열을 하나 만들고 Loop 돌리는 형태
function getMarketList() public view returns (NftTokenData[] memory ){
    uint[] memory onSaleNftToken = getSaleNftToken();
    NftTokenData[] memory onSaleNftTokens = new NftTokenData[](onSaleNftToken.length);

    for(uint i = 0; i < onSaleNftToken.length; i ++){
        uint tokenId = onSaleNftToken[i];
        uint tokenPrice = getNftTokenPrice(tokenId);
        onSaleNftTokens[i] = NftTokenData(tokenId, tokenURI(tokenId), tokenPrice) ;
    }

    return onSaleNftTokens;

}

 

해당 함수로 300wei에 등록되어 있는 NFT 확인 완료

 

 

5.  buyNft

function buyNft(uint256 _tokenId) public payable {
    // 금액
    uint256 price = nftTokenPrices[_tokenId];
    // 해당 nft 소유자
    address nftTokenOwner = ownerOf(_tokenId);

    // 제한사항, owner는 구매하지 못함. 
    require(price > 0, "nft token not sale.");
    require(price  <= msg.value, "caller sent lower than price.");
    require(nftTokenOwner != msg.sender,"caller is nft token owner.");
    // 상태가 false일때는 구매 못함.
    require(isApprovedForAll(nftTokenOwner, address(this)), "nft token owner did not approve token.");

    // 구매가 이루어지면 nft를 transfer
    payable(nftTokenOwner).transfer(msg.value);

    // 소유권 이전. IERC721에 정의된 스펙
    IERC721(address(this)).safeTransferFrom(nftTokenOwner, msg.sender, _tokenId);


    //판매 리스트에서 삭제
    removeToken(_tokenId);        

}

 

다른 계정으로 구매 시도. 300wei 로 등록되어 있는 NFT를 0wei 로 구매하려니 에러 발생.

 

 

300 wei로 구매 시도하니 정상적으로 완료.

 

 

구매자에게  1번 전달된거 확인

판매자한테서도 사라진 거 확인. 기존 3개에서 2개로 줄어듬.

반응형

댓글