修改智能合约进行NFT铸造

上一篇文章已经完成了一个简单的部署演示 如果需要进行NFT铸造的话 还需要再编写一些代码进行改进我们的 智能合约

重命名 .env 文件为 .env.development 并再新建一个 .env.production 的文件 用来区分 测试链 公链 的配置

.env.development.env.production 中的配置方式和之前的 .env 一样 为了方便描述 后面统称为 env 指的就是这两个配置文件

修改 package.json 中的 scripts 内的脚本为

"compile:rinkeby": "NODE_ENV=development npx hardhat compile",
"deploy:rinkeby": "NODE_ENV=development npx hardhat run scripts/deploy.js --network rinkeby"

并再添加下公链对应的脚本 完整的内容为

hardhat.config.js 中的 require('dotenv').config(); 改为

require('dotenv').config({ path: `.env.${process.env.NODE_ENV}` });

这样就可以动态的获取当前要执行的环境变量了

以上内容修改完之后 编译和部署命令将变更为

# 编译rinkeby测试链合约
npm run compile:rinkeby

# 部署rinkeby测试链合约
npm run deploy:rinkeby

env 中添加一个配置 NETWORK 表示要部署的网络 .env.development 就填 rinkeby.env.production 就填 homestead

例如

NETWORK = "rinkeby"

至于为什么这样填可以看下文档 https://docs.ethers.io/ethers.js/v3.0/html/api-providers.html

然后在 scripts 文件夹中新建 helpers.js 文件 添加以下内容

const { ethers } = require("ethers");

// Helper method for fetching environment variables from .env
function getEnvVariable(key) {
  if (process.env[key]) {
    return process.env[key];
  }
  throw `${key} is not defined and no default value was provided`;
}

// Helper method for fetching a connection provider to the Ethereum network
function getProvider() {
  return ethers.getDefaultProvider(getEnvVariable("NETWORK"), {
    alchemy: getEnvVariable("ALCHEMY_KEY"),
  });
}

// Helper method for fetching a wallet account using an environment variable for the PK
function getAccount() {
  return new ethers.Wallet(getEnvVariable("ACCOUNT_PRIVATE_KEY"), getProvider());
}

module.exports = {
  getEnvVariable,
  getProvider,
  getAccount,
}

这个文件提供了3个函数 getEnvVariable 根据 key 获取配置信息 OpenSea 文档 中 是有两个参数的 可以给一个默认值 我们这里不需要 因为我们已经用 NODE_ENV 环境变量区分了配置信息

getProvider 获取一个连接以太坊网络的提供者

getAccount 检查钱包账户信息

修改 scripts 文件夹中的deploy.js 文件为

const { task } = require("hardhat/config");
const { getAccount } = require("./helpers");

task("check-balance", "Prints out the balance of your account").setAction(async function (taskArguments, hre) {
  const account = getAccount();
  console.log(`Account balance for ${account.address}: ${await account.getBalance()}`);
});

task("deploy", "Deploys the NFTContract.sol contract").setAction(async function (taskArguments, hre) {
  const NFTContractFactory = await hre.ethers.getContractFactory("NFTContract", getAccount());
  const contract = await NFTContractFactory.deploy();
  console.log(`Contract deployed to address: ${contract.address}`);
});

这里创建了两个 Hardhattask 用来检查我们的账户信息和部署 智能合约

然后将 scripts 文件夹中的deploy.js 引入到 hardhat.config.js

require("./scripts/deploy.js");

可以在命令行运行一下以下命令 验证 task 是否创建成功

NODE_ENV=development npx hardhat

如果没有报错的话 应该就是添加成功了 下面的输出信息中可以找到我们添加的两个 task

然后可以使用 我们创建的 task 进行操作

查看 账户信息

NODE_ENV=development npx hardhat check-balance

部署 智能合约

NODE_ENV=development npx hardhat deploy

顺便将这些命令添加到 package.json 中的 scripts 内的脚本里吧

因为我们将部署 智能合约 的操作已经做成了 task 所以之前的部署脚本也要做下相应的修改 顺便也添加下部署到公链上的脚本

"compile:rinkeby": "NODE_ENV=development npx hardhat compile",
"hardhat:rinkeby": "NODE_ENV=development npx hardhat",
"check-balance:rinkeby": "NODE_ENV=development npx hardhat check-balance",
"deploy:rinkeby": "NODE_ENV=development npx hardhat deploy",
"compile:ethereum": "NODE_ENV=production npx hardhat compile",
"hardhat:ethereum": "NODE_ENV=production npx hardhat",
"check-balance:ethereum": "NODE_ENV=production npx hardhat check-balance",
"deploy:ethereum": "NODE_ENV=production npx hardhat deploy"

compile:xxx 编译指定网络的 智能合约hardhat:xxx 获取指定网络的 Hardhat taskcheck-balance:xxx 检查指定网络的钱包账户信息 deploy:xxx 部署指定网络的 智能合约

上面的步骤都完成后 就可以在命令行运行以下命令 在 Rinkeby 测试链上部署我们的 智能合约

记得重新编译一下 执行下编译命令 再部署即可

npm run deploy:rinkeby

部署完成后命令行会输出一条类似下面的消息

Contract deployed to address: 智能合约地址

上面的 智能合约 地址记得保存下来 后面需要使用 直接放到 env 中即可

NFT_CONTRACT_ADDRESS = "你刚部署的智能合约地址"

合约部署好了之后 我们就可以开始铸造(mint)我们的 NFT

scripts 文件夹中的helpers.js 文件中添加一个函数 getContract 完整的 helpers.js 文件内容如下

const { ethers } = require("ethers");
const { getContractAt } = require("@nomiclabs/hardhat-ethers/internal/helpers");

// Helper method for fetching environment variables from .env
function getEnvVariable(key) {
  if (process.env[key]) {
    return process.env[key];
  }
  throw `${key} is not defined and no default value was provided`;
}

// Helper method for fetching a connection provider to the Ethereum network
function getProvider() {
  return ethers.getDefaultProvider(getEnvVariable("NETWORK"), {
    alchemy: getEnvVariable("ALCHEMY_KEY"),
  });
}

// Helper method for fetching a wallet account using an environment variable for the PK
function getAccount() {
  return new ethers.Wallet(getEnvVariable("ACCOUNT_PRIVATE_KEY"), getProvider());
}

// Helper method for fetching a contract instance at a given address
function getContract(contractName, hre) {
  const account = getAccount();
  return getContractAt(hre, contractName, getEnvVariable("NFT_CONTRACT_ADDRESS"), account);
}

module.exports = {
  getEnvVariable,
  getProvider,
  getAccount,
  getContract,
}

然后在 scripts 文件夹中新建 mint.js 文件 添加以下内容

const { task } = require("hardhat/config");
const { getContract } = require("./helpers");

task("mint", "Mints from the NFT contract").addParam("address", "The address to receive a token").setAction(async function (taskArguments, hre) {
  const contract = await getContract("NFTContract", hre);
  const transactionResponse = await contract.mintTo(taskArguments.address, {
    gasLimit: 500_000,
  });
  console.log(`Transaction Hash: ${transactionResponse.hash}`);
});

这里创建了一个 Hardhattask 用来铸造(mint)NFT 其中的 gasLimit 指的是铸造(mint)时消耗 gas 的上限单位 值越大 费用越高 但也不能太小 太小的话可能会铸造失败(搬运费不够了 得加钱)

这里可以直接搜索下具体的含义(我没找到官方的文档 所以就不贴地址了)

然后将 scripts 文件夹中的mint.js 引入到 hardhat.config.js

require("./scripts/mint.js");

添加完成后 可以使用 npm run hardhat:rinkeby 查看下 task 是否添加成功

全部都完成后 就可以在命令行中使用下面的命令 进行铸造(mint)NFT 了 (需要支付 Gas Fee (矿工费))

NODE_ENV=development npx hardhat mint --address 你的钱包地址

不出意外的话 命令行会输出类似以下信息 就代表铸造(mint)成功了

Transaction Hash: 此次铸造(mint)的交易哈希值

可以在 Rinkeby Etherscan 上输入上面的交易哈希值 进行查看交易明细

也可以将这条命令添加到 package.json 中的 scripts 内的脚本里(公链上铸造(mint)的脚本的也添加下)

"mint:rinkeby": "NODE_ENV=development npx hardhat mint --address",
"mint:ethereum": "NODE_ENV=production npx hardhat mint --address"

命令行运行下面的命令就可以在对应网络上进行铸造(mint)了

npm run mint:xxx --address 你的钱包地址

铸造完成后 可以在 OpenSea测试网 进行查看你铸造(mint)的 NFT

打开后你会发现 图片是空的 因为我们还没有跟 原数据(metadata )进行关联 而且现在也无法让玩家进行自己铸造(mint) 后面的文章再做详细介绍吧

本篇文章代码 Github 地址 https://github.com/stephenml/nft-contract/tree/day-02

最后修改日期: 2022年7月10日

留言

撰写回覆或留言

发布留言必须填写的电子邮件地址不会公开。