Be lazy, Be crazy

web3 및 erc721 사용한 NFT 민팅 프로젝트 일기 (2) 본문

BlockChain/이더리움

web3 및 erc721 사용한 NFT 민팅 프로젝트 일기 (2)

정신이 많이없는 개발자 2022. 2. 5. 02:14
728x90
반응형
항상 모든것을 설명하기 위해서 자세하고 설명하도록 노력해보자!
공부한 내용을 바탕으로 도움이 될 수 있게 작성하려고 노력중입니다.
*잘못된 내용은 댓글로 남겨주시면 수정하겠습니다.*

 

  이번시간에는 저번 시간에 이어서 ipfs 값을 가지고 어떻게 NFT를 발행하는지 알아 봅시다.

제일먼저 순서를 생각해봅시다. 제가 올리는 블로그에서 순서는 react -> server -> blockChain 순서로 데이터가 들어갑니다.

 

* react 프론트에서 node.js 서버로 데이터를 넘겨주고 web3.js를 사용해서 mint를 진행

혹시나 순서는 먼저 contract를 작성한 후 배포해야지  web3.js를 사용해서 어플리케이션을 만드는 것이다.

Contract를 배포하는 부분은 2가지로 배포할 수 있다. remix를 사용하던지 truffle를 사용하던지 이부분에 대해서는 나중에 참고로 올릴 예정이다. 지금 이 글을 읽고 당장이라도 test를 사용하실 분들은 remix에 이대로 복붙하면 사용해 볼 수있다. 

*openzeppelin부분은 rexmix/VScode 각자 사용하는 곳에 맡게 사용하자. npm i @openzeppelin*

 

Erc20 토큰을 가지고 Erc-721 토큰을 구매할 수 있게 만들어 놓았다.
1. mintNFT => NFT를 발행하는 함수.
2.setTokenId => Erc-20토큰 이동을 가능 하도록 만들어 놓은 함수 
3.checkTokenId => tokenId값을 추적하기 위해서 ifps의 해쉬값이 유일무이하다는 점을 이용해서 만들어 놓은 함수
4. 주의깊게 보면 좋은 변수 => IERC20 token, mapping:getToekn
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

import "../node_modules/openzeppelin-solidity/contracts/token/ERC721/ERC721.sol";
import "../node_modules/openzeppelin-solidity/contracts/utils/Counters.sol";
import "../node_modules/openzeppelin-solidity/contracts/access/Ownable.sol";
import "../node_modules/openzeppelin-solidity/contracts//token/ERC721/extensions/ERC721URIStorage.sol";
import "../node_modules/openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";

contract NFTLootBox is ERC721URIStorage, Ownable {
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;
    IERC20 public token;
    uint256 public nftPrice;
    mapping (string => uint256) public getToken;

    constructor() ERC721("MyNFTs", "MNFT") {
       
        nftPrice = 100e18;
    }

    function mintNFT(address recipient, string memory tokenURI) public onlyOwner returns (uint256) {
        
        require(token.balanceOf(recipient) > nftPrice);

         //오류지점 
        token.transferFrom(recipient, msg.sender, nftPrice);
        
        _tokenIds.increment();
        uint256 newItemId = _tokenIds.current();
        _mint(recipient, newItemId);
        _setTokenURI(newItemId, tokenURI);
        getToken[tokenURI] = newItemId;

        return newItemId;
    }

    function setToken (address tokenAddress) public onlyOwner returns (bool) {
        require(tokenAddress != address(0x0));
        token = IERC20(tokenAddress);
        return true;
    }
    function checkTokenId(string memory tokenUri) public view returns(uint256){
        return getToken[tokenUri];
    }
}

 

위 컨트랙트를 배포 후 밑에 코드를 자세히 읽어보면 이해가 된다. 
1. Abi = 컨트랙트 배포하면서 생성된다.
2.var erc721Contract = new web3.eth.Contract(erc721Abi, process.env.nftCA);
          erc721Abi = abi, process.env.nftCA = 배포된 컨트랙트 주소 
3. 밑에 부분을 천천히 따라가다보면 어떻게 트랜잭션을 서버부분에서 보낼 수 있는지 확인해 볼 수 있다. 
const { userId, name, description, imgURI, path, price } = req.body.data;
  const data = {
    userId: userId,
    name: name,
    description: description,
    imgURI: imgURI,
    path: path,
    price: price
    
  };
  // 프론트에서 넘어오는 데이터를 받아주자.
  
  
  
  --------------------------------
  const Web3 = require('web3');	
  const web3 = new Web3(process.env.networkHost);
  var erc721Contract = new web3.eth.Contract(erc721Abi, process.env.nftCA);
  
// web3.js를 사용해서 node에서 Mint를 진행하는 부분 

    const sendAccount = process.env.serverAddress;
    const privateKey = process.env.serverAddress_PK;
    const tokenUri = `https://ipfs.io/ipfs/${metadata.path}`;
    const receiveAccount = '0x747b089fD11Da5032242818E2728A6444CAe464f';
    const nonce = await web3.eth.getTransactionCount(sendAccount, 'latest');
    const data = erc721Contract.methods
      .mintNFT(receiveAccount, tokenUri)
      .encodeABI();
      
    const tx = {
      from: sendAccount,
      to: process.env.nftCA,
      nonce: nonce,
      gas: 5000000,
      data: data,
    };

    const signPromise = web3.eth.accounts.signTransaction(tx, privateKey);
    let outTokenId = 0;

    signPromise
      .then((signedTx) => {
        web3.eth.sendSignedTransaction(
          signedTx.rawTransaction,
          async function (err, hash) {
            if (!err) {
              
              const tokenId = await erc721Contract.methods
                .checkTokenId(tokenUri)
                .call();

                console.log(tokenId+"mint");
                
               
              Metadata.create({
                userId: metadata.userId,
                name: metadata.name,
                description: metadata.description,
                imgURI: metadata.imgURI,
                tokenURI: tokenUri,
                tokenId: tokenId,
                price : metadata.price
              }).then((result) => {
               
              
                console.log('DB store success!');
               
              });
              
            } else {
              console.log('failed!');
            }
          }
        );
      })
      .catch((err) => {
        console.log('Promise failed:', err);
       
      });
     
  }

 

 

반응형
Comments