1. v0.0.1 구현/배포/테스트 방법
2024년 4월 7일
v0.0.1 #
NFT 발급 로직 #
클라이언트 #
- 이미지를 업로드하면, 32*32px 의 이미지로 축소 변환
- 이미지를 4등분 (2x2) 으로 나누고, 번호 부여
- 이미지 파편을 랜덤하게 조합해서 traits를 설정하고, 해당 tratis에 맞는 이미지를 조합. 원하는 갯수만큼 이미지 생성
- 만약 1,2,3,4 가 전부 순서대로 모여있는 경우 legend 등급이 되고 나머지는 abnormal 등급
- 만들어진 이미지를 10배정도 확대(320*320px)
- 기본적으로 HTML에서는 부드러운 경계 처리가 되기 때문에 blur를 제거하는 canvas 옵션을 사용해야 한다.
- 이미지 URL을 포함한 메타데이터를 오픈씨 형태로 IPFS같은 p2p 스토리지에 업로드
- infura는 현재 ipfs 관련 API를 사용할 수 없어서 pinata를 사용함
- 이미지 URL과 메타데이터 URL은 ipfs.io 로 변경해서 저장 (pinata를 통하는 것과 속도차이가 심함)
- 스마트 컨트랙트에 콜렉션 이름, 심볼, 메타데이터 주소배열을 전송해서 한꺼번에 여러 NFT 발급요청
스마트컨트랙트 #
대부분의 기능은 클라이언트에서 진행하기 때문에 스마트 컨트랙트는 그냥 콜렉션/NFT 생성 후 배치민팅만 하면 된다.
- 전달받은 정보로 콜렉션을 생성하고 NFT 생성 (콜렉션 이름, 심볼, tokenURIs)
- 배치 전송으로 만들어진 NFT를 한꺼번에 요청한 지갑으로 전송
NFT 조회 로직 #
스마트 컨트랙트 #
- 팩토리 컨트랙트에서 콜렉션 리스트를 관리
- 콜렉션 컨트랙트에서는 해당 유저에 대한 NFT Metadata 리스트를 view 함수로 구현
- view로 구현하면 가스비 없이 블록체인 조회관련 작업이 가능하다.
클라이언트 #
- 콜렉션 리스트를 가져옴
- view 함수로 현재 내 지갑의 NFT 메타데이터 리스트를 가져옴
- ipfs에서 메타데이터 요청
- 이때 메타데이터는 저장할 때 ipfs.io로 저장했기 때문에 빠르게 가져올 수 있다.
발생한 버그
- tokenURI를 사용하려면 ERC721URIStorage를 상속받아야 하고, totalSupply를 사용하려면 ERC721Enumerable을 상속받아야 한다. 샘플코드를 찾아서 그 코드를 기반으로 수정했더니 해결됨 ( https://medium.com/@juanxaviervalverde/erc721enumerable-extension-what-how-and-why-8ba3532ea195)
- 컨트랙트 안에서 mintNFT를 호출하기 때문에 Factory 컨트랙트에 소유권을 할당해야한다. 아니면 mint 함수에서 onlyOwner 속성을 제거해야하지만 그렇게되면 뭔가 이상하다.
로컬 네트워크에서 테스트 #
1. 배포 스크립트 작성 #
1// scripts/deploy.js
2async function main() {
3 // 컨트랙트 팩토리 가져오기
4 const ScamFactory = await ethers.getContractFactory("ScamFactory");
5
6 // 컨트랙트 배포
7 const scamFactory = await ScamFactory.deploy();
8 console.log("ScamFactory deployed to:", scamFactory.target);
9
10 // 생성된 컬렉션의 주소들 가져오기
11 const collections = await scamFactory.getCollections();
12 console.log("Created collections:", collections);
13}
14
15main()
16 .then(() => process.exit(0))
17 .catch(error => {
18 console.error(error);
19 process.exit(1);
20 });
2. 로컬 서버 실행 및 로컬서버에 배포 #
npx hardhat node
노드 서버의 주소를 기억한다. ex) http://127.0.0.1:8545npx hardhat run scripts/deploy.js --network localhost
배포된 ScamFactory의 컨트랙트 주소를 기억한다.
3. 스마트 컨트랙트 ABI를 클라이언트와 연결 #
-
blockchain/artifacts/contracts/ScamFactory.sol/ScamFactory.json파일을 그대로web/src/ScamFactory.json경로에 복사한다.
또는 import 할때import NewCollection from '../../blockchain/artifacts/contracts/NewCollection.sol/NewCollection.json';처럼 작성 -
클라이언트 소스코드에서 배포한 로컬 블록체인 네트워크 연결
노드 서버 주소를 클라이언트의 Web3 생성자에 넣는다.
const web3 = new Web3('http://localhost:8545'); -
nft 팩토리 컨트랙트를 연결한다.
const contract = new web3.eth.Contract(ScamFactory.abi, CONTRACT_ADDRESS);
4. 브라우저 메타마스크에서 네트워크와 계정 세팅 #
-
네트워크 추가
메타마스크에서 네트워크 직접 추가로 네트워크를 추가한다. hardhat 로컬 네트워크의 체인 ID는31337이며, 통화기호는 ETH를 쓰면 된다.
나는 SCAMNET을 이미 연결해서 중복된다고 표시된다.. -
계정 추가
hardhat 노드를 실행시키면 테스트를 위한 계정들이 생성되고 프라이빗 키가 출력된다.이 키를 이용해서 계정을 가져온다.
5. 클라이언트 실행 #
npm run dev
테스트넷 배포 #
-
polygonscan api 키 획득하기
polygonscan에서 회원가입 후 API 키 획득 -
hardhat.config.js 설정
npm install dotenv
1require("@nomicfoundation/hardhat-toolbox");
2require("dotenv").config();
3/** @type import('hardhat/config').HardhatUserConfig */
4module.exports = {
5 solidity: "0.8.24",
6 networks: {
7 amoy: {
8 url: "https://rpc-amoy.polygon.technology",
9 accounts: [`${process.env.PRIVATE_KEY}`]
10 }
11 },
12 etherscan: {
13 apiKey: `${process.env.POLYSCAN_APIKEY}`,
14 },
15};
-
테스트넷에 배포
npx hardhat run scripts/deploy.js --network amoy -
매일 코인 출석해서 모으기
https://www.alchemy.com/faucets/polygon-amoy
https://faucet.chainstack.com/amoy-faucet
https://www.alchemy.com/faucets/ethereum-sepolia
- 테스트넷 opensea에서 볼 수 있음
https://testnets.opensea.io/
메인넷에 배포 #
rpc 주소만 달라질 뿐 모든 작업이 같다.
1 polygon: {
2 url: "https://polygon-rpc.com",
3 accounts: [`0x${process.env.PRIVATE_KEY}`],
4 },
배포 완료하고 nft 테스트로 생성해봤는데, openSea에서도 보인다.