从零开始,构建你的第一个以太坊项目,一份完整教学指南

网络 阅读: 2025-12-06 20:49:48

以太坊,作为全球第二大加密货币和领先的智能合约平台,不仅仅是一种数字资产,更是一个去中心化的、可编程的世界计算机,它为开发者提供了构建去中心化应用(Dapps)的强大能力,从金融(DeFi)到游戏,从艺术品(NFT)到身份验证,其应用潜力无穷。

本指南将带领你,从一个完全的初学者开始,一步步完成一个完整的以太坊项目,我们将使用最流行和成熟的工具栈,涵盖从环境搭建、智能合约编写、前端交互到项目部署的全过程,无论你是否有编程经验,只要跟随本教程,你就能亲手打造出属于自己的第一个DApp。


第一部分:准备工作——搭建你的开发环境

在开始编码之前,我们需要安装几个核心工具,它们就像是你的“开发工具箱”。

  1. Node.js 和 npm (Node Package Manager)

    • 作用:JavaScript 运行环境和包管理器,我们将用它来运行代码、管理项目依赖。
    • 安装:访问 Node.js 官网 下载并安装 LTS(长期支持)版本,安装完成后,打开终端(或命令提示符),输入 node -vnpm -v 确认安装成功。
  2. 代码编辑器

    • 推荐Visual Studio Code (VS Code),它免费、强大,并拥有丰富的插件生态
    • 推荐插件
      • Solidity by Juan Blanco:提供智能合约的语法高亮、代码提示和格式化。
      • Hardhat for VS Code:为 Hardhat 框架提供更好的集成体验。
      • Prettier - Code formatter:保持代码风格统一。
  3. MetaMask 钱包

    • 作用:这是你与以太坊区块链交互的桥梁,它是一个浏览器插件钱包,用于管理你的账户、私钥,并与你的 DApp 进行连接。
    • 安装:访问 MetaMask 官网,下载对应浏览器的插件,并按照提示创建一个新钱包。请务必妥善保存你的助记词,这是你资产的唯一凭证,绝不泄露给任何人!
  4. 测试网 ETH

    • 作用:以太坊主网上的真实资产非常宝贵,不适合用于开发和测试,我们使用“测试网”,它是一个模拟的真实网络,其中的“测试ETH”没有实际价值,但可以免费获取,用于测试交易和部署。
    • 获取:你可以去 faucets.chain.link 等水龙头网站,使用你的 MetaMask 钱包地址免费获取 Sepolia 测试网的 ETH。

第二部分:项目构建——从智能合约到前端交互

我们将构建一个简单的“留言板”DApp,用户可以付费在链上留下一条留言,并查看所有留言。

步骤 1:初始化项目与安装框架

我们选择 Hardhat 作为我们的开发框架,它是一个功能全面的以太坊开发环境,能让编译、测试、部署和调试变得异常简单。

  1. 创建一个项目文件夹并进入:

    mkdir eth-message-board
    cd eth-message-board
  2. 初始化 npm 项目:

    npm init -y
  3. 安装 Hardhat:

    npm install --save-dev hardhat
  4. 初始化 Hardhat 项目:

    npx hardhat

    在交互式提示中,选择 "Create a JavaScript project",然后一路回车接受默认配置,这会创建一个包含 contracts/, scripts/, test/ 等标准目录结构。

步骤 2:编写智能合约

智能合约是以太坊应用的“后端逻辑”,它运行在区块链上。

  1. 打开 contracts/ 目录,删除 Lock.sol,然后创建一个新文件 MessageBoard.sol
  2. 编写以下代码:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// 导入 OpenZeppelin 的合约,以获得更安全的实现
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
/**MessageBoard
 * @dev 一个简单的留言板合约,允许用户支付费用来存储消息。
 */
contract MessageBoard {
    // 定义一个结构体来存储留言信息
    struct Message {
        address author;  // 留言作者地址
        string content; // 留言内容
        uint256 timestamp; // 留言时间戳
    }
    // 定义一个事件,用于在前端监听新留言
    event NewMessage(address indexed author, string content, uint256 timestamp);
    // 存储所有留言的数组
    Message[] public messages;
    // 定义留言费用(单位:wei,1 ETH = 10^18 wei)
    uint256 public constant MESSAGE_FEE = 1 ether;
    /**
     * @dev 提交一条新留言
     * @param _content 要提交的留言内容
     */
    function postMessage(string memory _content) public payable {
        // 确保用户支付了正确的费用
        require(msg.value == MESSAGE_FEE, "Incorrect message fee!");
        // 创建一个新的留言对象,并添加到数组中
        messages.push(Message({
            author: msg.sender,
            content: _content,
            timestamp: block.timestamp
        }));
        // 触发事件,通知前端
        emit NewMessage(msg.sender, _content, block.timestamp);
    }
    /**
     * @dev 获取所有留言的数量
     */
    function getMessagesCount() public view returns (uint256) {
        return messages.length;
    }
    /**
     * @dev 获取指定索引的留言
     */
    function getMessage(uint256 index) public view returns (address, string memory, uint256) {
        require(index < messages.length, "Message index out of bounds");
        Message storage message = messages[index];
        return (message.author, message.content, message.timestamp);
    }
}

代码解释

  • 我们定义了一个 Message 结构体来存储每条留言的作者、内容和时间。
  • postMessage 函数是核心功能,它要求用户支付 MESSAGE_FEE(1个测试ETH),然后将新留言存入数组,并触发 NewMessage 事件。
  • getMessagegetMessagesCount 是“查看”函数,它们不修改链上状态,因此成本很低,可以随时被调用。

步骤 3:编译与测试

  1. 安装依赖:我们需要 OpenZeppelin 的合约库来保证代码安全。

    npm install @openzeppelin/contracts
  2. 编译合约:在终端运行:

    npx hardhat compile

    成功后,你会在 artifacts/ 目录下看到编译好的合约字节码。

  3. 编写测试:在 test/ 目录下创建 messageBoard.test.js,编写测试用例来确保我们的合约按预期工作。

const { expect } = require("chai");
const { ethers } = require("hardhat");
describe("MessageBoard", function () {
    let MessageBoard;
    let messageBoard;
    let owner;
    let addr1;
    beforeEach(async function () {
        // 在每个测试前部署新的合约实例
        [owner, addr1] = await ethers.getSigners();
        MessageBoard = await ethers.getContractFactory("MessageBoard");
        messageBoard = await MessageBoard.deploy();
        await messageBoard.waitForDeployment();
    });
    it("Should post a message and emit an event", async function () {
        const messageContent = "Hello, Ethereum!";
        const fee = ethers.parseEther("1"); // 1 ETH in wei
        // 监听事件
        await expect(messageBoard.connect(addr1).postMessage(messageContent, { value: fee }))
            .to.emit(messageBoard, "NewMessage")
            .withArgs(addr1.address, messageContent, await ethers.provider.getBlock());
        // 验证留言是否被正确存储
        const messagesCount = await messageBoard.getMessagesCount();
        expect(messagesCount).to.equal(1);
        const message = await messageBoard.getMessage(0);
        expect(message.author).to.equal(addr1.address);
        expect(message.content).to.equal(messageContent);
    });
    it("Should not allow posting with incorrect fee", async function () {
        const messageContent = "This should fail";
        const wrongFee = ethers.parseEther("0.5"); // 支付的费用不足
        await expect(
            messageBoard.connect(addr1).postMessage(messageContent, { value: wrongFee })
        ).to.be.revertedWith("Incorrect message fee!");
    });
});
  1. 运行测试
    npx hardhat test

本文 原创,转载保留链接!网址:https://licai.bangqike.com/bixun/1275405.html

标签:
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

扫一扫关注我们,了解最新精彩内容

搜索