관리 메뉴

caLAB

[유니티 NFT 개발] 오픈씨(OpenSea)에 NFT 민팅하기 본문

Unity/유니티 NFT 개발

[유니티 NFT 개발] 오픈씨(OpenSea)에 NFT 민팅하기

도이(doi) 2022. 4. 12. 20:11
728x90

안녕하세요. DOI 입니다.

정말 오랜만에 기술 관련 게시물을 올리게 된 것 같네요.

최근에 퇴사하고 nft 게임 개발을 진행중인데요.

 

nft 관련 기술 공부한 것들을 블로그에 올려서 공유하고자 합니다 :)

오늘은 우선 NFT를 민팅하고 해당 nft에 metadata를 저장하는 방법에 대해서 알아보도록 하겠습니다.

저는 폴리곤 기반의 metamask를 연동해서 게임을 개발할 계획입니다.

우선은 비용 지불 없이 개발하기 위해서 testnet기반으로 개발을 진행하도록 한다는 점 참고해주시고. 

사이트에서 확인하실 때도 꼭 testnet사이트에서 진행 상황을 확인해보셔야 체크 가능한 점 염두해주세요.

 

개념 설명

https://sonny6786.tistory.com/11

 

NFT 배포를 위한 TokenURI (Metadata) 생성

안녕하세요 :) 이번 시간에는 대체 불가능 토큰(NFT)을 위한 TokenURI를 생성하는 방법에 대해 알아봅시다! 필요한 것 / Prerequisite * NFT.storage API Key * Installing IPFS * Code Editor (VSCode) *Content..

sonny6786.tistory.com

NFT 민팅하기 과정

1. Pinata에 NFT로 Deploy(배포)할이미지 폴더 IPFS 에 업로드

2. 이미지 파일에 대한 정보를 갖고 있는 json 형식의 metaData 생성 및 Pinata에 업로드

3. ERC1155 형식으로 RinkeyBy 테스트넷에 배포 

4. 일괄적으로(Batch) 민팅하기

*배치작업은, 데이터를 실시간으로 처리하는게 아니라, 일괄적으로 모아서 처리하는 작업을 의미한다. 가령, 하루동안 쌓인 데이터를 배치작업을 통해 특정 시간에 한꺼번에 처리하는 경우가 이에 해당한다. 은행의 정산작업과 같은 업무에서 이런 일괄처리를 수행하게 되며 사용자에게 빠른 응답이 필요하지 않은 서비스에 적용할 수 있다. 특정 시간이후에는 자원을 거의 소비하지 않는 것이 특징이다.

 

간단하게 레몬 그랩 이미지를 구글에서 크롤링 한 후에 이 이미지들을 NFT로 발행해보겠다.

 

1. 우선 레몬 그랩 크롤링은 Fatkun이라는 확장프로그램을 사용해서 하였다.

2. 이후 파일 형식을 png로 모두 맞춰줘야 해서 관련 jpg to png 변환 사이트에서 파일 변환을 하여 파일 형식 통일을 해주었다. 

https://jpg2png.com/

 

Convert JPEG to PNG

This free online tool converts your JPG images to PNG format, applying proper compression methods.

jpg2png.com

3. 그 후 아래 프로젝트 파일을 다운 받아서 visual code로 실행해준다. 

https://github.com/neha01/NFT

 

GitHub - neha01/NFT: Collection of smart contracts to mint NFT's on testnet & mainnet on Ethereum/Polygon

Collection of smart contracts to mint NFT's on testnet & mainnet on Ethereum/Polygon - GitHub - neha01/NFT: Collection of smart contracts to mint NFT's on testnet & mainnet on Eth...

github.com

4. images 폴더를 새로 생성한 후에 

png로 변환한 이미지들을 해당 폴더에 모두 넣어준다. 

 

5. 파일 이름이 숫자로 되도록 변환하는 코드가 있는데 visual code에서 terminal을 open 한 후에 해당 코드를 실행해주면 이미지 파일 이름이 숫자로 아름답게 변환된다. 

* 참고로 그냥 변환을 할 경우에 16진수로 변환되는데 나는 그게 싫어서 코드를 10진수로 표현되도록 수정하였다. 

원래 toString(16)으로 변환하는 것을 toString(10)으로 수정하였다.

6. 해당 작업이 완료되면 Pinata에 이미지 파일들이 있는 폴더를 업로드 한다. 

7. 그 이후에 이미지들에 대한 metadata를 생성해준다. 

Config.json에 자신의 프로젝트 이름으로 변경. base URI는 Pinata에서 주소 복사
Pinata에 있는 CID 주소를 복사해서 ipfs://를 타입한 후 붙여주면 된다.
이 후 위의 코드를 실행시켜 주면 metadata가 생성된다.
메타 데이터 생성 완료 XD

8. 생성된 metadata 폴더를 pinata에 업로드 한다.

9. 그 후 metamask 가입과 rinkeby네트워크에서 테스트할 가짜 ethereum을 받아야 된다. 

해당 방법은 참고 튜토리얼의 18:41 지점에서 확인하시길. (본인은 이미 진행되어 있기 때문에 생략)

 

10. remix.ethereum 사이트에 들어간다.

https://remix.ethereum.org/?#optimize=false&runs=200&evmVersion=null&version=soljson-v0.8.7+commit.e28d00a7.js 

 

Remix - Ethereum IDE

 

remix.ethereum.org

11. contracts에 ArtCollectible.sol이라는 파일을 새로 생성하고 아래 코드를 복사 붙여넣기 해준다.

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

import '@openzeppelin/contracts/token/ERC1155/ERC1155.sol';
import '@openzeppelin/contracts/access/Ownable.sol';

contract ArtCollectible is Ownable, ERC1155 {
    // Base URI
    string private baseURI;
    string public name;

    constructor()
        ERC1155(
            'ipfs://QmUusoGauKGU6EsGDLbqPiZK8PEnHDRYHa4c9yvJxhTHcg/{id}.json'
        )
    {
        setName('Mandelbrot Julia Set Collection');
    }

    function setURI(string memory _newuri) public onlyOwner {
        _setURI(_newuri);
    }

    function setName(string memory _name) public onlyOwner {
        name = _name;
    }

    function mintBatch(uint256[] memory ids, uint256[] memory amounts)
        public
        onlyOwner
    {
        _mintBatch(msg.sender, ids, amounts, '');
    }

    function mint(uint256 id, uint256 amount) public onlyOwner {
        _mint(msg.sender, id, amount, '');
    }
}

12. 그 이후 compile해주고 Environment와 Contract를 아래와 같이 변경해준다. 

13. 코드에서 constructor함수에 있는 부분에 ipfs:// 뒤의 주소를 본인의 메타 데이터 폴더의 pinata주소를 복사 붙여넣기 해준다.

14. 가짜 이더리움이 들어 있는 metamask를 연결한 후에 deploy 버튼을 눌러줘서 contract를 배포한다.

성공하면 console창에 초록색 체크 표시가 생김

15. Remix에 script폴더 안에 bulk mint기능의 js 스크립트를 추가.

// Right click on the script name and hit 'Run' to execute
(async () => {
    try {
        const totalNfts = 145;

        console.log('Running bulk_mint_nfts script...');

        const contractName = 'ArtCollectible'; // Change this for other contract
        const contract_address = 'YOUR_DEPLOYED_CONTRACT_ADDRESS';

        // Note that the script needs the ABI which is generated from the compilation artifact.
        // Make sure contract is compiled and artifacts are generated
        const artifactsPath = `browser/contracts/artifacts/${contractName}.json`; // Change this for different path

        const metadata = JSON.parse(
            await remix.call('fileManager', 'getFile', artifactsPath)
        );
        const accounts = await web3.eth.getAccounts();

        const artCollectible = new web3.eth.Contract(
            metadata.abi,
            contract_address,
            {
                from: accounts[0]
            }
        );

        // NFT's to mint in each transaction
        const mintSize = 100;
        for (let i = 1, j = totalNfts; i <= j; i += mintSize) {
            if (mintSize === 0) {
                throw new Error(
                    'Please specify greater than zero value for mintSize'
                );
            }
            let currentMintSize = mintSize;
            if (i + mintSize <= totalNfts + 1) {
                currentMintSize = mintSize;
            } else {
                // case when totalNfts is not a multiple of mintSize
                currentMintSize = totalNfts - i + 1;
            }
            // array containing tokenIds
            const ids = getTokenIds(i, currentMintSize);
            // array containing amount to mint for each tokenId, 1 in case of NFT's
            const amounts = getAmounts(currentMintSize);
            console.log('Token Ids to be minted in current batch => ', ids);
            console.log(
                'Amounts to be minted for each Token Id in current batch => ',
                amounts
            );
            await artCollectible.methods
                .mintBatch(ids, amounts)
                .send({ from: accounts[0] });
            console.log('successfully batch minted NFTs for current batch');
        }

        // https://docs.openzeppelin.com/contracts/2.x/api/token/erc721#IERC721-balanceOf-address-
        // returns number of NFT's in owner's account for tokenID 1
        const balance = await artCollectible.methods
            .balanceOf(accounts[0], 1)
            .call();
        console.log('balance: ', balance);
    } catch (e) {
        console.log(e.message);
    }
})();

function getTokenIds(startTokenId, size) {
    return Array(size)
        .fill()
        .map((element, index) => index + startTokenId);
}

function getAmounts(size) {
    return Array(size).fill(1);
}

9번째 줄에 당신의 contract_address를 입력하세요.
Deployed Contracts의 주소를 복사하면 됨. 이게 Contract Address

16. bulk_mint_nfts.js 실행하면 지갑 인증하라고 나오고 Successfully batch minted NFTs for current batch라고 나옴. 

https://rinkeby.etherscan.io/address/0x863ba5e5aB50caA4A5728509FEF0495eB31177B1

EtherScan에서 내역 확인 가능.

 

Contract Address 0x863ba5e5aB50caA4A5728509FEF0495eB31177B1 | Etherscan

The Contract Address 0x863ba5e5aB50caA4A5728509FEF0495eB31177B1 page allows users to view the source code, transactions, balances, and analytics for the contract address. Users can also interact and make transactions to the contract directly on Etherscan.

rinkeby.etherscan.io

17. 이후 opensea에 가서 collection에 추가되었는지 확인하면 되는데. opensea의 속도가 느려서 대략 30분 정도 기다렸다가 확인해야 된다...나는 우선 한 개만 mint해서 코드가 잘 작동하는지 체크해보았다.

 

이것으로 민팅 완료!

 

[참고 튜토리얼]

https://www.youtube.com/watch?v=KbhiAaRdgwc&t=194s 

 

728x90
반응형
Comments