Hardhat是个solidity开发工具,他提供了一个内部的EVM节点运行环境。可以让你离线本地编写测试solidity代码。同时他还提供了Nodejs的编程环境,方便开发者封装合约交互工具。
Hardhat 是个 solidity 开发工具,他提供了一个内部的 EVM 节点运行环境。可以让你离线本地编写测试solidity 代码。同时他还提供了 Nodejs 的编程环境,方便开发者封装合约交互工具。
具体参看 : https://hardhat.org/hardhat-runner/docs/getting-started
本文通过实例介绍如何通过hardhat 发布一个全链web3站点,部署完成后,你就可以通过web3url 访问了。
npm install --save-dev hardhat
这里选择了 Create a TypeScript project 环境。
部署完成后,你的项目代码里会包含几个目录 。
networks 中添加 mumbai 网络配置
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
require("dotenv").config();
const config: HardhatUserConfig = {
solidity: "0.8.19",
networks: {
mumbai: {
url: `https://polygon-mumbai.g.alchemy.com/v2/${process.env.ALCHEMY_API_KEY}`,
// url: "https://rpc-mumbai.maticvigil.com/",
accounts: [`0x${process.env.PRIVATE_KEY}`],
},
},
};
export default config;
需要提前准备好部署账号的私钥,其中包含一些测试 Token .
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;
contract Page {
bytes32 public constant resolveMode = "manual";
mapping(bytes => string) public uriContents;
address payable public owner;
constructor() payable {
owner = payable(msg.sender);
}
function setMapping(bytes calldata pathinfo, string memory content) public {
uriContents[pathinfo] = content;
}
fallback(bytes calldata pathinfo) external returns (bytes memory) {
if (bytes(uriContents[pathinfo]).length != 0) {
return abi.encode(uriContents[pathinfo]);
}
return abi.encode("<script>location.href='/index.html';</script>");
}
}
bytes32 public constant resolveMode = "manual";
声明为 manual 模式。注: 只有在 manual 模式中才可以使用mime 输出指定格式的内容,否则,content-type 均为空,浏览器会默认理解为 html
pnpm hardhat compile
pnpm hardhat test
hardhat run --network mumbai scripts/deploy.ts
部署的时候,需要指定网络。
pnpm create vite@latest --template react-ts
由于站点本身生成的 index bundle 过大一般 1M 左右,在上传过程中消耗大量的 gas ,所以,建议使用cdn 资源替代。
安装 vite-plugin-cdn2 和 vite-plugin-inspect , 在vite.config.ts 中添加 cdn 配置:
import { defineConfig } from "vite";
import React from "@vitejs/plugin-react";
import Inspect from "vite-plugin-inspect";
import { cdn } from "vite-plugin-cdn2";
import { chunkSplitPlugin } from "vite-plugin-chunk-split";
export default defineConfig(({ command }) => {
return {
plugins: [
chunkSplitPlugin({
strategy: "single-vendor",
}),
React(),
cdn({
modules: [
{ name: "react", relativeModule: "./umd/react.production.min.js" },
{
name: "react-dom",
relativeModule: "./umd/react-dom.production.min.js",
aliases: ["client"],
},
],
apply: command,
}),
Inspect(),
]
};
});
pnpm build 生成 dist 对应文件。
以上过程,封装成了一个简单的 ts 脚本,将 部署合约,上传资源合并到了一期。
脚本如下:
import { ethers } from "hardhat";
import * as fs from "fs/promises";
import path from "path";
async function main() {
const deployPath = "vite-project/dist";
const provider = ethers.provider;
const [deployer] = await ethers.getSigners();
console.log("Deploying contracts with the account:", deployer.address);
const balance = await provider.getBalance(deployer.address);
console.log(`deploy balance is : ${balance}`);
const lockedAmount = ethers.parseEther("0.001");
if (balance.valueOf() > lockedAmount.valueOf()) {
const page = await ethers.deployContract("Page", [], {
value: lockedAmount,
});
await page.waitForDeployment();
console.log(
`Lock with ${ethers.formatEther(lockedAmount)} ETH and deployed to ${
page.target
}`
);
const processFile = async (filePath: string) => {
try {
const content = await fs.readFile(filePath, "utf8");
const uri = filePath.replace(deployPath, "");
console.log(
`Processing file: ${filePath} len: ${content.length} to URI: ${uri}`
);
const tx = await page.setMapping(ethers.toUtf8Bytes(uri), content);
console.log(
`Transaction for ${uri} sent, waiting for confirmation ${tx.hash}`
);
await tx.wait();
console.log(`Transaction for ${uri} completed`);
console.log(
`web3 url is : https://${page.target}.80001.w3link.io${uri}. sleep 3 seconds ....`
);
await new Promise((resolve, reject) => {
setTimeout(() => {
console.log("do next Transaction!");
resolve(true);
}, 3000);
});
} catch (error) {
console.error(`Error processing file ${filePath}:`, error);
}
};
const traverseDirectory = async (directoryPath: string) => {
try {
const files = await fs.readdir(directoryPath);
for (const file of files) {
const fullPath = path.join(directoryPath, file);
const stats = await fs.stat(fullPath);
if (stats.isDirectory()) {
await traverseDirectory(fullPath);
} else if (stats.isFile()) {
await processFile(fullPath);
}
}
} catch (error) {
console.error(`Error reading directory ${directoryPath}:`, error);
}
};
await traverseDirectory(deployPath);
} else {
console.log("Insufficient funds");
}
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
参考项目: https://github.com/v1xingyue/hardhat-tutorial
部署完成后,有两种方式可以访问你的站点:
web3://$address.networkid/ 或者: 网关模式:
https://$address.$networkid.w3link.io
更复杂的方式,可参看 web3url 的设置。 https://w3url.w3eth.io/#/
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!