본문 바로가기
프로그래밍/프로젝트

NFT 민팅 사이트 만들기

by monicada 2022. 8. 17.
728x90

NFT 민팅 사이트 완성 

 

숙경의 민팅 사이트

 

ssukhackathon.netlify.app

전체 만든 과정 

1. 프로그램을 이용해서 자동으로 조합된 이미지와 JSON파일 준비 

피그마를 활용하여 이미지 생성

 

Figma

Created with Figma

www.figma.com

위에는 내가 작성한 nft이미지를 담은 피그마 파일이다 (여러개를 요소별로 만들어 다양한 조합을 유도)

비주얼 스튜디오를 들어가서 코드 작성

//index.js

const nftName = "K-Birdz Egg";
const description = "K-Birdz, Flappy Bird Style P2E game with K-culture made by youtuber JoCoding";
const hiddenImgUrl = "ipfs://QmbbfqR9EHdEY2Jy2dJYx8jjFftoaMnD6vgKJLMFXemVdL/hidden.mp4";
const totalNum = 5;

try {
    for (let i = 1; i <= totalNum; i++) {
        let json = `{"name":"${nftName} #${i}","description":"${description}","image":"${hiddenImgUrl}","attributes":[{"trait_type": "Unknown","value": "Unknown"}]}`;
        let fs = require("fs");
        fs.writeFile(`json/${i}.json`, json, "utf8", (e)=>(e));
    }
    console.log("complete!");
} catch (error) {
    console.log(error);
}

//저절로 완성된 json파일 예시
{"name":"K-Birdz Egg #2","description":"K-Birdz, Flappy Bird Style P2E game with K-culture made by youtuber JoCoding","image":"ipfs://QmbbfqR9EHdEY2Jy2dJYx8jjFftoaMnD6vgKJLMFXemVdL/hidden.mp4","attributes":[{"trait_type": "Unknown","value": "Unknown"}]}

작성한 vscode 모습

 

2. 이미지와 제이슨 파일을 IPFS라고 불리는 분산형 저장소에 저장 

Index of /ipfs/QmRoNzzMs1WeSzGSzduxsjgFynARcYF9siU78JmVjvdW8R

 

 

Pinata | Your home for NFT media

Welcome to Pinata - Your home for NFT Media. We power the web3 space distributing content for NFTs across some of the top marketplaces, metaverses, apps and more. Get started today on your web3 journey.

www.pinata.cloud

IPFS분산 저장을 도와주는 위 서비스를 이용

위의 코드를 업로드하면 제이슨 파일이 생김 

제이슨 파일이 생긴 모습

3. Kaikas 지갑 생성

 

Kaikas

클레이튼 블록체인 지갑을 웹 브라우저에서 만나보세요

chrome.google.com

크롬의 확장 프로그램 추가를 통해서 카이카스 지갑을 설치한다 

사용할 비밀번호 입력, 생성하고 시드부분이 나온다 정말 잘 보관해야한다 신원확인할 때 계속 시드물어본다 

 

Klaytn IDE

 

ide.klaytn.foundation

위 사이트 들어가면 온라인 상에서 솔리디티 코드를 작성하고 배포할 수 있도록 도와준다 내 컴퓨터에 설치하지 않아도 되는 것이 장점 

이런 식으로 생김

 

4. 생성한 위 주소를 통해 배포 준비 

테스트용일 경우 이와 같이 설정하여 배포 진행

//index.html

<!DOCTYPE html>
<html lang="ko">

<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>숙경의 민팅 사이트</title>
	<script src="config.js"></script>
	<script src="mintScript.js"></script>
	<script src="https://cdnjs.cloudflare.com/ajax/libs/bignumber.js/8.0.2/bignumber.js" integrity="sha512-XQDG6H87RgMf+aNFwDPCUcFwUf3t9liyqN/2BkJ8KGixupbjPwQHNhypNA972mLIkg4KPo4lkGmqAf3yfDz8hw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>

<body>
	<h1>숙경의 민팅 사이트</h1>
	<h2>MINTING INFO</h2>
	<p id="blockNubmer">현재 블록: #00000000</p>
	<p id="mintStartBlockNumber">민팅 시작 블록: #00000000</p>
	<p id="mintPrice">민팅 가격: 0 KLAY</p>
	<p id="mintLimitPerBlock">트랜잭션당 최대 수량: 0개</p>
	<a href="https://scope.klaytn.com/">현재 블록넘버 확인하기1(Klaytnscope)</a><br>
	<a href="https://klayswap.com/">현재 블록넘버 확인하기2(Klayswap)</a><br>
	<hr/>
	<h2>MY WALLET</h2>
	<button onclick="connect()">카이카스 지갑연결</button>
	<p id="myWallet">지갑주소: 연결되지 않음</p>
	<p id="myKlay">잔액: 연결되지 않음</p>
	<hr/>
\	<h2>MINT</h2>
	<p id="mintCnt">0 / 0</p>
	<label for="amount">민팅 수량</label>
	<input type="number" id="amount" name="amount" min="1" max="3" value="1">
	<button onclick="publicMint()">민팅</button>
	<hr/>
	<script>
		document.addEventListener("DOMContentLoaded", async function (event) {
			const accounts = await klaytn.enable();
			if (!accounts) {
				alert("KaiKas 확장 프로그램을 활성화 해주세요!");
			}
			check_status();
		});
	</script>
</body>

</html>
//mintScript.js

let account;
let mintIndexForSale = 0;
let maxSaleAmount = 0;
let mintPrice = 0;
let mintStartBlockNumber = 0;
let mintLimitPerBlock = 0;

let blockNumber = 0;
let blockCnt = false;

function cntBlockNumber() {
    if(!blockCnt) {
        setInterval(function(){
            blockNumber+=1;
            document.getElementById("blockNubmer").innerHTML = "현재 블록: #" + blockNumber;
        }, 1000);
        blockCnt = true;
    }
}

async function connect() {
    const accounts = await klaytn.enable();
    if (klaytn.networkVersion === 8217) {
        console.log("메인넷");
    } else if (klaytn.networkVersion === 1001) {
        console.log("테스트넷");
    } else {
        alert("ERROR: 클레이튼 네트워크로 연결되지 않았습니다!");
        return;
    }
    account = accounts[0];
    caver.klay.getBalance(account)
        .then(function (balance) {
            document.getElementById("myWallet").innerHTML = `지갑주소: ${account}`
            document.getElementById("myKlay").innerHTML = `잔액: ${caver.utils.fromPeb(balance, "KLAY")} KLAY`
        });
    await check_status();
}

async function check_status() {
    const myContract = new caver.klay.Contract(ABI, CONTRACTADDRESS);
    await myContract.methods.mintingInformation().call()
        .then(function (result) {
            console.log(result);
            mintIndexForSale = parseInt(result[1]);
            mintLimitPerBlock = parseInt(result[2]);
            mintStartBlockNumber = parseInt(result[4]);
            maxSaleAmount = parseInt(result[5]);
            mintPrice = parseInt(result[6]);
            document.getElementById("mintCnt").innerHTML = `${mintIndexForSale - 1} / ${maxSaleAmount}`;
            document.getElementById("mintLimitPerBlock").innerHTML = `트랜잭션당 최대 수량: ${mintLimitPerBlock}개`;
            document.getElementById('amount').max = mintLimitPerBlock;
            document.getElementById("mintStartBlockNumber").innerHTML = `민팅 시작 블록: #${mintStartBlockNumber}`;
            document.getElementById("mintPrice").innerHTML = `민팅 가격: ${caver.utils.fromPeb(mintPrice, "KLAY")} KLAY`;
        })
        .catch(function (error) {
            console.log(error);
        });
    blockNumber = await caver.klay.getBlockNumber();
    document.getElementById("blockNubmer").innerHTML = "현재 블록: #" + blockNumber;
    cntBlockNumber();
}

async function publicMint() {
    if (klaytn.networkVersion === 8217) {
        console.log("메인넷");
    } else if (klaytn.networkVersion === 1001) {
        console.log("테스트넷");
    } else {
        alert("ERROR: 클레이튼 네트워크로 연결되지 않았습니다!");
        return;
    }
    if (!account) {
        alert("ERROR: 지갑을 연결해주세요!");
        return;
    }

    const myContract = new caver.klay.Contract(ABI, CONTRACTADDRESS);
    const amount = document.getElementById('amount').value;
    await check_status();
    if (maxSaleAmount + 1 <= mintIndexForSale) {
        alert("모든 물량이 소진되었습니다.");
        return;
    } else if (blockNumber <= mintStartBlockNumber) {
        alert("아직 민팅이 시작되지 않았습니다.");
        return;
    }
    const total_value = BigNumber(amount * mintPrice);

    try {
        const gasAmount = await myContract.methods.publicMint(amount).estimateGas({
            from: account,
            gas: 6000000,
            value: total_value
        })
        const result = await myContract.methods.publicMint(amount).send({
            from: account,
            gas: gasAmount,
            value: total_value
        })
        if (result != null) {
            console.log(result);
            alert("민팅에 성공하였습니다.");
        }
    } catch (error) {
        console.log(error);
        alert("민팅에 실패하였습니다.");
    }
}

코드를 작성한 화면

 

5. 무료 배포 홈페이지인 Netlify를 활용하여 배포 

 

Netlify: Develop & deploy the best web experiences in record time

A powerful serverless platform with an intuitive git-based workflow. Automated deployments, shareable previews, and much more. Get started for free!

www.netlify.com

완료한 화면

 

 

 

 

 

'프로그래밍 > 프로젝트' 카테고리의 다른 글

프로젝트 관리하기  (0) 2022.08.23
Stack Overflow 클론코딩 레퍼런스 찾기  (0) 2022.08.19
TDD - Testbuilder 과제  (0) 2022.08.03
프로젝트 경험 설명  (0) 2022.07.28
번들링과 웹팩(web-pack)  (0) 2022.07.25

댓글