OpeaSea CloneCoding

OpenSea는 대표적인 NFT 마켓입니다.

이번시간에는 OpeaSea의 일부 기능을 만들어보는 시간을 갖도록 하겠습니다.

개발할 기능은
1. NFT minting-NFT를 발행하기
2. NFT 전송하기
입니다.

그럼 위 두 가지 기능을 가지는 프로젝트를 만들어 보겠습니다.

프로젝트 개발에 앞서,
프론트 엔드는 Reactjs를 활용하여 간단한 사용자 인터페이스를 구현합니다.
그리고 백 엔드는 Ethereum Ropsten TestNetwork를 사용하여 구현합니다.

먼저 NFT를 발행해보겠습니다.
remixIDE에 NFT를 발행하는 코드를 작성해 보겠습니다.
ERC721.sol 파일을 추가한 뒤, 아래 코드를 작성합니다.

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

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";

contract cozNFTs is ERC721URIStorage, Ownable, ERC721Enumerable {
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;

    constructor() public ERC721("cozNFT", "NFT") {}

    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal override(ERC721, ERC721Enumerable) {
        super._beforeTokenTransfer(from, to, tokenId);
    }

    function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {
        super._burn(tokenId);
    }

  function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721Enumerable) returns (bool) {
        return super.supportsInterface(interfaceId);
    }
    function tokenURI(uint256 tokenId) public view override(ERC721, ERC721URIStorage) returns (string memory) {
        return super.tokenURI(tokenId);
    }
    
    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;
    }
}

해당 코드를 Ropsten TestNet에서 deploy 한 후,
mintNFT 메소드를 통해, 이미지 파일을 본인 지갑 주소에 minting을 진행합니다.
백 엔드 상에서 NFT를 발행하는 기능은 여기서 마무리 됩니다.

이제, React 프로젝트 생성해 프론트 엔드 단을 개발해 보겠습니다.
아래 명령어를 통해 React 프로젝트를 생성합니다.

npx create-react-app web3-practice

생성된 프로젝트 폴더 상에서 사용하지 않을 파일들(App.test.js, logo.svg, reportWebVitals.js, setupTests.js)를 삭제합니다.
index.js 코드는 아래와 같이 수정합니다.

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

EIP-1139를 통해 웹페이지에 자바스크립트 객체 형태로 window.ethereum 객체를 제공합니다.
이 window.ethereum은 공급자 객체로 web3.js를 사용하게 해줍니다.
아래 명령어로 web3를 설치합니다.

npm install web3

주의 web3를 설치 후, web3를 임포트 하면 polyfill 관련 에러가 발생합니다.
에러에 대한 해결책으로 react 패키지 버전에 따른 문제로
package.json 파일에 아래 의존성 라이브러리를 추가합니다.

  "dependencies": {
	...
    "react-scripts": "4.0.3",
    "reactstrap": "8.9.0",
	...
  },

프론트 페이지의 결과 형태는 아래와 같은 그림과 같습니다.

첫번째 버튼(지갑연결)은 메타마스크 지갑에 연결해 주는 기능이며,
두번째 버튼(NFT 리스팅)은 연결된 지갑이 소유한 NFT 리스트를 보여줍니다.
NFT 리스트를 보기 위해서는,
Minting Contract Address 또는 Transfer From Contract Address를 입력해야합니다.
리스트업된 NFT는 다시 전송될 지갑주소를 입력 후, 세번째 버튼(NFT 전송)을 누르면
입력된 지갑 주소로 NFT를 전송합니다.

React 프로젝트의 소스 코드는 깃헙링크 에서 확인할 수 있습니다.

추후 추가 개발할 사항으로
1. 프론트 엔드 CSS 작업
2. NFT drop
등을 계획하고 있습니다.

좋은 웹페이지 즐겨찾기