Cover photo

Alchemy Road to Web3第三周:铸造 NFT并刷新元数据

TL;DR:这周教程也是一共包括六个步骤,目的是部署一个NFT合约,并与之进行交互,刷新元数据。主要内容包括:准备/搭建环境/代码编译/部署合约/合约交互/发布与提交。

第一步、准备:

1、结合之前前序文档,创建好本周的github代码库以及同步到replit.com上。

如图,依次点击右上角github账号--“repositories”--“new”--填写“name”(随意)--“create repository”(切记勾选“add a README file”不然会是一个空库,无法导入replit)

post image
post image

2、登陆你的replit账号,依次点击“create”--“import”,然后选择上一步创建的代码库“magweek3”,再次点击“import from github”,完成代码的导入工作。

(注意在开始这一步之前,必须要先关联好github账号,如何关联请看之前前序

post image
post image

导入完成之后,点击“DONE”

post image

第二步、环境搭建

1、回到replit左边栏,删除掉README.md。

post image

2、点击右侧“Shell”,创建ChainBattle目录并进入,输入mkdir ChainBattle并回车,然后输入cd ChainBattle并回车。(以下步骤的命令都是在“shell”中输入)

post image

2、输入npm init -y并回车(中间可能会要再次回车一次)。

post image

3、输入npm install hardhat并回车,等待安装完成,如下图所示。

post image

4、输入npx hardhat init并回车,(中间应该需要点5次回车,多点几次也无妨😆,warn不用管)等待安装完成,如下图所示。

post image
post image

5、输入npm install @openzeppelin/contracts并回车,等待安装完成,如下图。

post image

6、输入npm install @nomiclabs/hardhat-etherscan并回车,等待安装完成,如下图。

post image

7、输入npm install @nomiclabs/hardhat-waffle并回车,等待安装完成,如下图。

post image

8、输入npm install dotenv并回车,等待安装完成,如下图。

至此所有环境搭建已经完成,中途应该不会遇到本地环境兼容问题🏂,这就是网页端搭建的好处。

post image

第三步、代码编译

1、打开contracts目录,把Lock.sol重命名为ChainBattles.sol。

post image

2、将上一步重命名为ChainBattles.sol的文件里的内容替换为以下代码。

post image

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

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; import "@openzeppelin/contracts/utils/Counters.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import "@openzeppelin/contracts/utils/Base64.sol";

contract ChainBattles is ERC721URIStorage { using Strings for uint256; using Counters for Counters.Counter; Counters.Counter private _tokenIds;

mapping(uint256 => uint256) public tokenIdToLevels;

constructor() ERC721 ("Chain Battles", "CBTLS"){
}

function generateCharacter(uint256 tokenId) public returns(string memory){

bytes memory svg = abi.encodePacked(
    '<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 350 350">',
    '<style>.base { fill: white; font-family: serif; font-size: 14px; }</style>',
    '<rect width="100%" height="100%" fill="black" />',
    '<text x="50%" y="40%" class="base" dominant-baseline="middle" text-anchor="middle">',"Warrior",'</text>',
    '<text x="50%" y="50%" class="base" dominant-baseline="middle" text-anchor="middle">', "Levels: ",getLevels(tokenId),'</text>',
    '</svg>'
);
return string(
    abi.encodePacked(
        "data:image/svg+xml;base64,",
        Base64.encode(svg)
    )    
);

} function getLevels(uint256 tokenId) public view returns (string memory) { uint256 levels = tokenIdToLevels[tokenId]; return levels.toString(); } function getTokenURI(uint256 tokenId) public returns (string memory){ bytes memory dataURI = abi.encodePacked( '{', '"name": "Chain Battles #', tokenId.toString(), '",', '"description": "Battles on chain",', '"image": "', generateCharacter(tokenId), '"', '}' ); return string( abi.encodePacked( "data:application/json;base64,", Base64.encode(dataURI) ) ); } function mint() public { _tokenIds.increment(); uint256 newItemId = _tokenIds.current(); _safeMint(msg.sender, newItemId); tokenIdToLevels[newItemId] = 0; _setTokenURI(newItemId, getTokenURI(newItemId)); } function train(uint256 tokenId)public{ require(_exists(tokenId)); require(ownerOf(tokenId)==msg.sender,"You must own this token to train it"); uint256 currentLevel=tokenIdToLevels[tokenId]; tokenIdToLevels[tokenId]=currentLevel+1; _setTokenURI(tokenId,getTokenURI(tokenId)); } }

3、在ChainBattle文件夹下新建.env文件,并在该文件内输入以下代码。

post image

TESTNET_RPC=

PRIVATE_KEY=

POLYGONSCAN_API_KEY=

4、在alchemy.com里面创建(如何创建详见:之前前序)一个Polygon Mumbai网络的APP,复制其URL粘贴到.env的TESTNET_RPC=后面

post image

将metamask钱包的新建小号私钥导出(如何导出详见:之前前序),并复制粘贴到PRIVATE_KEY=后面。

进入polygonscan.com,登陆你的账号(需要先注册这里不赘述)依次点击“API keys”-- “Add”创建一个API。

post image

然后复制你刚才创建的那个API代码粘贴到POLYGONSCAN_API_KEY=后面,如下图红框内。

post image

5、最后.env文件内的代码大概如下图所示。

post image

6、打开hardhat.config.js文件,将一下代码粘贴进去,如图所示。

post image

require("dotenv").config();

require("@nomiclabs/hardhat-waffle");

require("@nomiclabs/hardhat-etherscan");

module.exports = {

solidity: "0.8.10",

networks: {

mumbai: {

url: process.env.TESTNET_RPC,

accounts: [process.env.PRIVATE_KEY]

},

},

etherscan: {

apiKey: process.env.POLYGONSCAN_API_KEY

}

};

7、代码编译已经完成,测试一下是否编译成功。在Shell那边输入npx hardhat compile并回车(中间大概需要5次回车🚒)。

post image

第四步、部署合约

1、添加好mumbai测试网及领取测试币。

①进入chainlist.info,搜索mumbai,将matic测试网添加到Metamask钱包。

post image

②进入https://mumbaifaucet.com/,右上角登陆Alchemy账号,粘贴钱包地址,点击“Send Me Matic”获取测试币。

post image

2、然后回到Replit,打开scripts/deploy.js,将原文替换成以下代码。

post image

const main = async () => { try { const nftContractFactory = await hre.ethers.getContractFactory( "ChainBattles" ); const nftContract = await nftContractFactory.deploy(); await nftContract.deployed();

  console.log("Contract deployed to:", nftContract.address);
  process.exit(0);
} catch (error) {
  console.log(error);
  process.exit(1);
}

};

main();

4、在Shell处输入npx hardhat run scripts/deploy.js --network mumbai并回车(中间可能会有一次回车)。

post image

5、点击Metamask钱包三点处,然后点区块浏览器,然后弹出新新网页查看合约地址是否一致,并等待contract处是否出现✅。如若没有,则输入npx hardhat verify --network mumbai +你的合约地址,进行验证。

post image
post image
post image

最终出现“successfully submit”则代表合约部署已经成功完成。

第五步、合约交互

1、切换到之前打开的合约网页上,点开Contract--Write contract--connect to web3,在弹出的钱包中点确定,连接之前对应的私钥钱包。

post image

2、点击第4个“mint”下的write,在钱包中确认,等待交互成功。

post image

3、前往 testnet.opensea.com ,连接我们刚才的钱包,点击profile,找到我们刚才mint的nft,点进去会发现如下图所示。

post image
post image

4、继续回到合约那边,选到第8个train,在框中输入1,点击write,弹出小狐狸,点确认等待链上确认成功。

post image

5、再次回到testnet.opensea.com 刷新网页,如下图所示,可以看到0变成1了,表示该任务已经成功完成。

post image

第六步、发布与提交

1、如图点击publish,填好description然后一直点下一步即可发布成功,保存好最后出来的那个网址,作为提交证明。

post image
post image

2、提交到github,提交之前记得删除.env(保险起见)。

post image

将代码提交到github,并在你的github账号查看提交记录,复制好你的github本周代码库网址(图二红框处)作为任务提交证明。

post image

3、任务提交https://forms.gle/DdnKrEvKzUHK4yLH9

主要是三个链接:1第四步第4点部署到合约地址,2第六步第1点获取的published地址

3第六步第2点获取的github代码库地址。