跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
SolidityNode.js大前端

前端调用 Solidity 智能合约连接 MetaMask 钱包并部署至 Alchemy 测试网

如何构建基于 Solidity 的智能合约 DApp。内容包括编写 Counter 合约、配置 Hardhat 环境、使用 ethers.js 连接 MetaMask 钱包实现前端交互,以及通过 Alchemy 节点将合约部署到 Sepolia 测试网。教程涵盖了从本地开发到测试网部署的完整流程,包括私钥管理、网络配置及交易验证。

星河入梦发布于 2026/4/6更新于 2026/7/2154 浏览
前端调用 Solidity 智能合约连接 MetaMask 钱包并部署至 Alchemy 测试网

1. DApp 前端代码

在 VSCode 中右键,新增 src 目录,新建 index.html 和 index.ts 文件。

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
</body>
</html>

index.ts

import { ethers } from "ethers";
import { abi } from '../artifacts/contracts/Counter.sol/Counter.json';

function getEth() {
    const eth = window.ethereum;
    if (!eth) {
        throw new Error("No ethereum provider found");
    }
    return eth;
}

async  () {
     eth = ();
     result =  eth.({ :  })  [];
     result && result. > ;
}

  () {
     metamask = ();
     signers =  metamask.({ :  })  [];
     signers. > ;
}

  () {
     (! () && ! ()) {
          ();
    }
     provider =  ethers.(());
     address = ;
     contract =  ethers.(address, abi,  provider.());

     counter = .();
      () {
        counter. =  contract.();
    }
    ();

     btn = .();
    btn. = ;
    btn. =   () {
         contract.();
    }

    contract.(contract..(),   () {
        counter. = args[].() ||  contract.();
    });

    ..(counter);
    ..(btn);
}

  () {
     ();
}
();
function
requestAccess
const
getEth
const
await
request
method
"eth_requestAccounts"
as
string
return
length
0
async
function
hasSigners
const
getEth
const
await
request
method
"eth_accounts"
as
string
return
length
0
async
function
getContract
if
await
hasSigners
await
requestAccess
throw
new
Error
"No ethereum provider found"
const
new
BrowserProvider
getEth
const
"0x5FbDB2315678afecb367f032d93F642f64180aa3"
const
new
Contract
await
getSigner
const
document
createElement
"div"
async
function
getCount
innerHTML
await
getCount
getCount
const
document
createElement
"button"
innerHTML
"increment"
onclick
async
function
await
count
on
filters
CounterInc
async
function
{ args }
innerHTML
0
toString
await
getCount
document
body
appendChild
document
body
appendChild
async
function
main
await
getContract
main

在 package.json 所在目录下新建 webpack.common.js、webpack.dev.js、webpack.prod.js 及 .env 文件。

webpack.common.js

const dotenv = require("dotenv");
dotenv.config();
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
    entry: "./src/index.ts",
    output: {
        path: path.resolve(__dirname, "dist"),
        filename: "[name].js",
    },
    resolve: {
        extensions: [".js", ".ts", ".json"],
    },
    module: {
        rules: [
            {
                test: /\.ts$/,
                loader: "ts-loader",
                exclude: /node_modules/,
            },
            {
                test: /\.css$/i,
                use: ["style-loader", "css-loader"],
            },
        ],
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./src/index.html",
            inject: "body",
        }),
    ],
};

webpack.dev.js

const webpack = require("webpack");
const { merge } = require("webpack-merge");
const baseConfig = require("./webpack.common");

module.exports = merge(baseConfig, {
    mode: "development",
    plugins: [
        new webpack.DefinePlugin({
            'process.env.CONTRACT_ADDRESS': JSON.stringify(process.env.CONTRACT_ADDRESS),
            'process.env.DEBUG': JSON.stringify(process.env.DEBUG),
        }),
    ],
    devServer: {
        historyApiFallback: true,
        port: 8080,
        hot: true
    }
});

webpack.prod.js

const webpack = require("webpack");
const baseConfig = require("./webpack.common");
const { merge } = require("webpack-merge");

module.exports = merge(baseConfig, {
    mode: "production",
    plugins: [
        new webpack.DefinePlugin({
            'process.env.CONTRACT_ADDRESS': JSON.stringify(process.env.CONTRACT_ADDRESS),
            'process.env.DEBUG': JSON.stringify(process.env.DEBUG),
        }),
    ],
});

.env 文件

PRIVATE_KEY=私钥地址
ALCHEMY_API_KEY=ALCHEMY 的 key

package.json 配置

{
    "scripts": {
        "dev": "webpack serve --config webpack.dev.js",
        "build": "webpack --config webpack.prod.js",
        "deploy:local": "npx hardhat run scripts/deploy-counter.ts --network localhost"
    }
}

2. Solidity 代码

在 contracts 目录下新建 Counter.sol 文件。

pragma solidity ^0.8.24;
import "hardhat/console.sol";

contract Counter {
    uint counter;
    event CounterInc(uint counter);

    function count() public {
        counter++;
        console.log("Now, counter is: ", counter);
        emit CounterInc(counter);
    }

    function getCount() public view returns (uint) {
        return counter;
    }
}

3. 编写部署代码

在 package.json 所有目录下新增 scripts 目录,创建 deploy-counter.ts 文件。

import "@nomicfoundation/hardhat-ethers";
import { ethers } from "hardhat";

async function deploy() {
    const Counter = await ethers.getContractFactory("Counter");
    const counter = await Counter.deploy();
    await counter.waitForDeployment();
    console.log('counter address is', await counter.getAddress());
    return counter;
}

async function count(counter: any) {
    await counter.count();
    console.log('count is', await counter.getCount());
}

deploy().then(count);

4. 连接小狐狸钱包

安装 MetaMask 扩展。打开浏览器访问 https://metamask.io/zh-CN/download 下载并添加扩展。

创建钱包时建议使用助记词方式,完全自主控制。屏幕显示 12 个单词后请立即手抄保存,不要拍照。

首先在根目录执行以下命令启动本地以太坊区块链节点:

npx hardhat node

注意控制台输出的地址 http://127.0.0.1:8545/,在 MetaMask 中配置自定义 RPC 网络。

导出测试私钥并导入 MetaMask,确保账户拥有测试 ETH 余额。

5. 启动 Webpack 开发服务器

首先部署合约(在另一个终端窗口):

npx hardhat run scripts/deploy-counter.ts --network localhost

启动 Webpack 开发服务器:

npx webpack serve --config webpack.dev.js

在浏览器中输入 http://localhost:8080 访问页面。

点击连接按钮授权 MetaMask,然后点击 'increment' 按钮调用合约函数。确认弹窗即代表发送区块链交易,合约计数器将递增并触发事件更新界面。

6. 部署到 Alchemy 测试网

注册 Alchemy 账号并创建应用,获取 API Key。

编辑 .env 文件,填入私钥和 Alchemy API Key:

PRIVATE_KEY=填写刚刚复制的私钥,添加前缀 0x
ALCHEMY_API_KEY=nr6k9FBd4Rvwi83XSr6xR

从 Endpoint URL 复制 Sepolia 网络地址,例如:https://eth-sepolia.g.alchemy.com/v2/${API_KEY}

编辑 hardhat.config.ts 文件,配置 sepolia_eth 网络:

import "hardhat-gas-reporter";
import "@nomicfoundation/hardhat-toolbox";
import "@nomicfoundation/hardhat-ethers";
import "@nomicfoundation/hardhat-verify";
const dotenv = require('dotenv');
dotenv.config();
type Config = import('hardhat/config').HardhatUserConfig;

const config: Config = {
    solidity: "0.8.28",
    networks: {
        hardhat: { chainId: 31337 },
        sepolia_eth: {
            url: `https://eth-sepolia.g.alchemy.com/v2/${process.env.ALCHEMY_API_KEY}`,
            accounts: [process.env.PRIVATE_KEY]
        }
    },
    gasReporter: {
        enabled: true
    }
};
export default config;

修改 tsconfig.json,注释掉 "strict": true 以避免编译错误。

运行部署命令:

npx hardhat run scripts/deploy-counter.ts --network sepolia_eth

成功后,可在 Etherscan 测试网验证器查询合约地址:https://sepolia.etherscan.io/

注意区分主网与测试网,本教程仅涉及测试网部署。

目录

  1. 1. DApp 前端代码
  2. 2. Solidity 代码
  3. 3. 编写部署代码
  4. 4. 连接小狐狸钱包
  5. 5. 启动 Webpack 开发服务器
  6. 6. 部署到 Alchemy 测试网
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Kotlin 语言核心特性与常见陷阱测试题解析
  • 基于 Web Components 的跨框架组件库实践
  • VSCode + GitHub Copilot AI 编程实战教程
  • 基于 Whisper-large-v3 的多语言翻译系统开发
  • Grok 开源发布:程序员在大模型时代的技术机遇
  • Abseil C++ 库完整指南:提升现代 C++ 开发效率
  • Go 语言 Gin 框架详解与快速入门
  • Kotlin 根据日期获取星座的实现
  • 文艺青年学 Python 转行:从北漂到程序员的职业进阶之路
  • 前缀和算法详解:一维、二维及经典题目
  • FAIR plus 机器人全产业链接会聚焦具身智能与产业链协同
  • Java 网络编程:Socket 套接字基础与实现
  • JDK 动态代理与 CGLIB 动态代理区别及 Spring AOP 适配原理
  • MySQL 高频用户统计方法
  • ClawX:基于 Electron 的可视化 AI 智能体工具实践
  • 在昇腾 NPU 上部署与测评 CodeLlama-7b-Python
  • OpenClaw 本地部署指南:接入 Kimi K2.5 实现办公自动化
  • 动态规划:买卖股票最佳时机(含冷冻期与手续费)
  • 普通产品经理转型 AI 产品经理的准备指南
  • 西门子 S7-1500 PLC 与 Fanuc 机器人焊装系统集成及 Profinet 通讯

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online