从零开始构建你的第一个DApp,以太坊开发实战教程全解析

 :2026-02-11 21:57    点击:20  

以太坊,作为全球领先的智能合约平台,不仅开创了去中心化应用(DApps)的新纪元,也为开发者和创业者提供了无限的创新可能,本教程将带你从环境搭建到智能合约编写,再到前端交互,一步步完成一个简单的以太坊DApp开发实战,助你快速入门以太坊开发的世界。

开发环境准备:工欲善其事,必先利其器

在正式开始之前,我们需要准备好一系列开发工具:

  1. Node.js 和 npm:JavaScript 运行时环境和包管理器,建议从 随机配图
href="https://nodejs.org/">Node.js 官网 下载 LTS 版本。
  • Truffle Suite:以太坊最受欢迎的开发框架之一,包含开发环境、测试框架和资产管道,它简化了智能合约的编译、测试和部署流程。
    • 安装:npm install -g truffle
  • Ganache:一款个人区块链,用于快速部署和测试智能合约,它会在本地创建一个区块链网络,并提供预设的测试账户和以太坊。
  • MetaMask:一款浏览器插件钱包,用于与以太坊区块链交互,在开发中,它可以模拟用户钱包,让我们能够与本地或测试网的智能合约进行交互。
    • 安装:从 MetaMask 官网 或浏览器应用商店安装,并创建一个测试账户。
  • 代码编辑器:推荐使用 Visual Studio Code (VS Code),并安装 Solidity 插件以获得语法高亮和智能提示。
  • Git:版本控制工具,用于管理代码。
  • 创建项目结构

    1. 创建一个新的项目文件夹,my-first-dapp,并在终端中进入该文件夹。
    2. 初始化一个新的 Truffle 项目:
      truffle init

      这会生成以下标准目录结构:

      • contracts/:存放 Solidity 智能合约文件。
      • migrations/:存放部署脚本文件。
      • test/:存放测试文件。
      • truffle-config.js:Truffle 配置文件。

    编写智能合约

    我们的目标是创建一个简单的“存储合约”,允许用户存储和获取一个字符串。

    1. contracts 目录下创建一个新的 Solidity 文件,Storage.sol

    2. 编写以下合约代码:

      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.0;
      /**
       * @title Storage
       * @dev 一个简单的存储合约,允许用户存储和检索一个字符串。
       */
      contract Storage {
          string private storedData;
          event DataStored(string newData);
          /**
           * @dev 存储一个字符串。
           * @param _data 要存储的字符串。
           */
          function set(string memory _data) public {
              storedData = _data;
              emit DataStored(_data);
          }
          /**
           * @dev 获取存储的字符串。
           * @return 存储的字符串。
           */
          function get() public view returns (string memory) {
              return storedData;
          }
      }

    编译智能合约

    在终端中,确保你位于项目根目录,运行以下命令编译合约:

    truffle compile

    如果成功,你会在 build/contracts 目录下看到编译后的合约 JSON 文件,其中包含合约的 ABI(应用程序二进制接口)和字节码。

    编写部署脚本

    1. migrations 目录下创建一个新的迁移脚本文件,2_deploy_storage.js

    2. 编写以下部署代码:

      const Storage = artifacts.require("Storage");
      module.exports = function (deployer) {
        deployer.deploy(Storage);
      };

    部署到本地 Ganache 网络

    1. 确保你的 Ganache 已经启动并运行。
    2. truffle-config.js 中,确保已经配置了本地开发网络,默认情况下,Truffle 会自动检测 Ganache,如果没有,你需要手动添加网络配置:
      module.exports = {
        // ... 其他配置
        networks: {
          development: {
            host: "127.0.0.1",     // Localhost (default: none)
            port: 7545,            // Standard Ethereum port (default: none)
            network_id: "*",       // Any network (default: none)
          },
        },
        // ... 其他配置
      };
    3. 部署合约到本地网络:
      truffle migrate --network development

      如果成功,你会在终端看到部署的合约地址,Ganache 的交易列表中会显示相应的部署交易。

    创建前端界面与智能合约交互

    1. 在项目根目录下创建一个 src 文件夹,用于存放前端代码。

    2. src 文件夹下创建 index.htmlapp.js

    3. index.html:

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>以太坊存储DApp</title>
          <style>
              body { font-family: Arial, sans-serif; margin: 20px; }
              input, button { padding: 8px; margin: 5px; }
              #result { margin-top: 10px; font-weight: bold; }
          </style>
      </head>
      <body>
          <h1>以太坊存储DApp</h1>
          <div>
              <input type="text" id="dataInput" placeholder="输入要存储的数据">
              <button onclick="setData()">存储数据</button>
          </div>
          <div>
              <button onclick="getData()">获取数据</button>
              <div id="result">结果将显示在这里...</div>
          </div>
          <script src="app.js"></script>
      </body>
      </html>
    4. app.js:

      // 引入 Web3 库 (假设通过 CDN 引入)
      // 在实际项目中,你可以使用 npm install web3
      if (typeof web3 !== 'undefined') {
          web3 = new Web3(web3.currentProvider);
      } else {
          // 如果没有 MetaMask,则连接到本地 Ganache
          web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:7545"));
      }
      // 合约地址和 ABI (从 build/contracts/Storage.json 复制)
      const contractAddress = '0x...'; // 替换为你的部署合约地址
      const contractABI = [
          // 从 build/contracts/Storage.json 中复制 ABI 数组
          // 
          // {
          //     "constant": false,
          //     "inputs": [
          //         {
          //             "name": "_data",
          //             "type": "string"
          //         }
          //     ],
          //     "name": "set",
          //     "outputs": [],
          //     "payable": false,
          //     "stateMutability": "nonpayable",
          //     "type": "function"
          // },
          // {
          //     "constant": true,
          //     "inputs": [],
          //     "name": "get",
          //     "outputs": [
          //         {
          //             "name": "",
          //             "type": "string"
          //         }
          //     ],
          //     "payable": false,
          //     "stateMutability": "view",
          //     "type": "function"
          // }
      ];
      // 创建合约实例
      const storageContract = new web3.eth.Contract(contractABI, contractAddress);
      // 获取当前账户
      let currentAccount;
      web3.eth.getAccounts().then(accounts => {
          currentAccount = accounts[0];
          console.log("当前账户:", currentAccount);
      });
      // 存储数据
      async function setData() {
          const dataInput = document.getElementById('dataInput').value;
          if (!dataInput) {
              alert("请输入数据!");
              return;
          }
          try {
              await storageContract.methods.set(dataInput).send({ from: currentAccount });
              alert("数据存储成功!");
              document.getElementById('dataInput').value = "";
          } catch (error) {
              console.error("存储数据失败:", error);
              alert("存储数据失败:" + error.message);
          }
      }
      // 获取数据
      async function getData() {
          try {
              const result = await storageContract.methods.get().call();
              document.getElementById('result').innerText = "存储的数据:

    本文由用户投稿上传,若侵权请提供版权资料并联系删除!

    热门文章