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

By [Licrazy](https://paragraph.com/@doger) · 2022-08-29

---

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

### 第一步、准备：

1、结合[之前前序](https://mirror.xyz/doger.eth/UwHqj3KpiH_YIgNV_KgkliLcf2fwatK8_cKiXAfZZ6E)文档，创建好本周的github代码库以及同步到replit.com上。

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

![](https://storage.googleapis.com/papyrus_images/ebceb3f97fe943eb30a7240565bd9a87d95240d917e8375141a4ff6e258e8620.png)

![](https://storage.googleapis.com/papyrus_images/33d05c0e6c7439bdc8c4a4a816d813b5dbebe34bcd119300ff8da282b928b141.png)

2、登陆你的[replit](https://replit.com/)账号，依次点击“create”--“import”，然后选择上一步创建的代码库“magweek3”，再次点击“import from github”，完成代码的导入工作。

（注意在开始这一步之前，必须要先关联好github账号，如何关联请看[之前前序](https://mirror.xyz/doger.eth/UwHqj3KpiH_YIgNV_KgkliLcf2fwatK8_cKiXAfZZ6E)）

![](https://storage.googleapis.com/papyrus_images/8ae1ed9088c2606267667ea811ac788ea31473d3fcf65edab4aaebadec39dffe.png)

![](https://storage.googleapis.com/papyrus_images/2f0840c7b43c13a44f8437833366e8130bf452c357a1ebec8a8f717cc767d461.png)

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

![](https://storage.googleapis.com/papyrus_images/6d52ef579b044f48db22f87424fbdaf260bb81c87f80eb8a16bc712c6d970eb6.png)

### 第二步、环境搭建

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

![](https://storage.googleapis.com/papyrus_images/ba8aea5ec8c567447b62432e55ed360f51336a272fecbf643889e17e82368f31.png)

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

![](https://storage.googleapis.com/papyrus_images/d09f23b6c8f2291d7f565df72d9af1acf50975a3805bc814f89a074124877f1b.png)

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

![](https://storage.googleapis.com/papyrus_images/84dbb5fa0b941a1596d4d00de833db6884c420514df8e08d4990c1659bc9097d.png)

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

![](https://storage.googleapis.com/papyrus_images/c5393055f7fdaf9fe26b83a1b937f3f6319b784bff41b9d4dcb8db62b6cdb7ee.png)

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

![](https://storage.googleapis.com/papyrus_images/c7d13758da61103f2e4ed7a2ccf150d2869777569d97bb83764b18fa9ae4a4cd.png)

![](https://storage.googleapis.com/papyrus_images/91f7e6ceff6844365f0508930e54c829fb988bebea1e51a1adef6b0e9fa1a859.png)

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

![](https://storage.googleapis.com/papyrus_images/02673251fab7a2fc5ba7c47e8eccd6d5ecae6bb012c40b5ada88be352a999493.png)

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

![](https://storage.googleapis.com/papyrus_images/161573f0c1399cc952d8d3c1e4ad2a9ddbaed7a792e0bf50cf156a894854bd4f.png)

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

![](https://storage.googleapis.com/papyrus_images/d599dbcc390d56a19aa8183d853df331f5a7820c13e83db57c2a6036adbeaef4.png)

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

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

![](https://storage.googleapis.com/papyrus_images/3e5bf21d4cbf596ee58bca754078c7df26e3a7d6fd40c2f717fc3a0fbb0c3921.png)

### 第三步、代码编译

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

![](https://storage.googleapis.com/papyrus_images/c095c7015048315912b7bcf3d6b2580297f0f3018d18a34978c4ddb1dc99e784.png)

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

![](https://storage.googleapis.com/papyrus_images/479da0f8c358e6ee235d8f00066e58c71eeee159c48176d4739c528efc679eaa.png)

// 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文件，并在该文件内输入以下代码。

![](https://storage.googleapis.com/papyrus_images/d69cefeb9be398814c931a1b2003355417a223bd92c4cec45df862af8b148e43.png)

TESTNET\_RPC=

PRIVATE\_KEY=

POLYGONSCAN\_API\_KEY=

4、在alchemy.com里面创建（如何创建详见:[之前前序](https://mirror.xyz/doger.eth/UwHqj3KpiH_YIgNV_KgkliLcf2fwatK8_cKiXAfZZ6E)）一个Polygon Mumbai网络的APP，**复制其URL粘贴到.env的TESTNET\_RPC=后面**

![](https://storage.googleapis.com/papyrus_images/83a1f35533c89430576b6f3413528e8db14f56b017b807c7123afd3dea8a850a.png)

将metamask钱包的新建小号私钥导出（如何导出详见:[之前前序](https://mirror.xyz/doger.eth/UwHqj3KpiH_YIgNV_KgkliLcf2fwatK8_cKiXAfZZ6E)），**并复制粘贴到PRIVATE\_KEY=后面。**

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

![](https://storage.googleapis.com/papyrus_images/45d2a45783dc8ae69aa080035bdd816b0240f5621c9b79227ce41e2a082d585b.png)

然后**复制你刚才创建的那个API代码粘贴到POLYGONSCAN\_API\_KEY=后面**，如下图红框内。

![](https://storage.googleapis.com/papyrus_images/9ece1cea3f91427a77ee740aba9b1e001d27b792344da3f59194f32817a618ad.png)

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

![](https://storage.googleapis.com/papyrus_images/fac5e5e3dc8f2689589c16ceb4cf83f9236f1f14ab9ebe6197d3e6ddfdaee6c0.png)

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

![](https://storage.googleapis.com/papyrus_images/c5c94194b6d4eb644ac685bf3186fdae9bbb662ed7b2eb682ba100bc41a4f759.png)

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次回车🚒）。

![](https://storage.googleapis.com/papyrus_images/9f5c3efa76b72fd9275e88cecbfa545e5823f13029d5529194adaac21746b887.png)

### 第四步、部署合约

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

①进入[chainlist.info](https://chainlist.info)，搜索mumbai，将matic测试网添加到Metamask钱包。

![](https://storage.googleapis.com/papyrus_images/60583346a20365facc10ead5392e4728f19bef8b4359273b0239d8e410d35e6c.png)

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

![](https://storage.googleapis.com/papyrus_images/2407db2e827beb46f5a7b7f6e75a975bf4bcb87882e423dd0d02dd4c36091046.png)

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

![](https://storage.googleapis.com/papyrus_images/156ba42bf4a45068bcb638170a7be819412f02a0aafe506954286abc8c7c6c29.png)

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并回车（中间可能会有一次回车）。

![](https://storage.googleapis.com/papyrus_images/7cff8391c45fede21199a0731e7e8bf58882d26bfc703b85e8fe86e4c4f809f7.png)

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

![](https://storage.googleapis.com/papyrus_images/a748e18c5f8b22462e4088ff84b250e24be22827fa09688f189aa8d0bef5b04e.png)

![](https://storage.googleapis.com/papyrus_images/0a9652392a8417ed423a9aacb8912a6bf785aa094f3b2c9a040ddb63929d961a.png)

![](https://storage.googleapis.com/papyrus_images/9345399c86ec39127da338efc59374fc6a164affecae770f8d78633b536ef81e.png)

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

### 第五步、合约交互

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

![](https://storage.googleapis.com/papyrus_images/d2563b21164226bc465c2e438f2e9eadb429693d1adf4f5b98b4479d5107af61.png)

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

![](https://storage.googleapis.com/papyrus_images/4923cb37de751f127a196af26b8a2cdf110f02f7408349a5c3d8cb70d5ed129b.png)

3、前往 [testnet.opensea.com](http://testnet.opensea.com) ，连接我们刚才的钱包，点击profile，找到我们刚才mint的nft，点进去会发现如下图所示。

![](https://storage.googleapis.com/papyrus_images/4d18d7d1f4cadbc575f2fa4f991d946f3f4c8b4101fa44b5bc73e6700443bb21.png)

![](https://storage.googleapis.com/papyrus_images/3a652f1f78da22e4d80efb1e1940eaf41270c404fce13947c611bd0324a359d2.png)

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

![](https://storage.googleapis.com/papyrus_images/2e7fb934bb41c50b4a7e1a218c94b68898ebf89839b3df63ff159570816cdd74.png)

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

![](https://storage.googleapis.com/papyrus_images/1a14a41725d558e54a6406d1dcad2ee76cc5668f9db16951c8c946b94be1f269.png)

### 第六步、发布与提交

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

![](https://storage.googleapis.com/papyrus_images/6552d84f18baaecec9241bfc0f72d2295e152fe80acda6090e46ad9d99b26712.png)

![](https://storage.googleapis.com/papyrus_images/41bdeab629fa2a010f0bd6a3b7926d06e4a08ec28cbfa90fb82c54148f62927d.png)

2、提交到github，提交之前记得删除.env（保险起见）。

![](https://storage.googleapis.com/papyrus_images/5651fc15659b64ec9f2e6df790cd97755be141a0bd20a9c4b4f6d9db17b34d98.png)

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

![](https://storage.googleapis.com/papyrus_images/f251fc02df06bbaffeda8cc44c8c8312f7df7a47848a1bcf1cfbf06f633c42ed.png)

3、任务提交[https://forms.gle/DdnKrEvKzUHK4yLH9](https://forms.gle/DdnKrEvKzUHK4yLH9)

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

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

---

*Originally published on [Licrazy](https://paragraph.com/@doger/alchemy-road-to-web3-nft)*
