:2026-02-11 21:57 点击:8
以太坊,作为全球领先的智能合约平台,不仅开创了去中心化应用(DApps)的新纪元,也为开发者和创业者提供了无限的创新可能,本教程将带你从环境搭建到智能合约编写,再到前端交互,一步步完成一个简单的以太坊DApp开发实战,助你快速入门以太坊开发的世界。
开发环境准备:工欲善其事,必先利其器
在正式开始之前,我们需要准备好一系列开发工具:
npm install -g truffle创建项目结构
my-first-dapp,并在终端中进入该文件夹。truffle init
这会生成以下标准目录结构:
contracts/:存放 Solidity 智能合约文件。migrations/:存放部署脚本文件。test/:存放测试文件。truffle-config.js:Truffle 配置文件。编写智能合约
我们的目标是创建一个简单的“存储合约”,允许用户存储和获取一个字符串。
在 contracts 目录下创建一个新的 Solidity 文件,Storage.sol。
编写以下合约代码:
// 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
如果成功,你会在 
编写部署脚本
在 migrations 目录下创建一个新的迁移脚本文件,2_deploy_storage.js。
编写以下部署代码:
const Storage = artifacts.require("Storage");
module.exports = function (deployer) {
deployer.deploy(Storage);
};
部署到本地 Ganache 网络
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)
},
},
// ... 其他配置
};
truffle migrate --network development
如果成功,你会在终端看到部署的合约地址,Ganache 的交易列表中会显示相应的部署交易。
创建前端界面与智能合约交互
在项目根目录下创建一个 src 文件夹,用于存放前端代码。
在 src 文件夹下创建 index.html 和 app.js。
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>
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 = "存储的数据:
本文由用户投稿上传,若侵权请提供版权资料并联系删除!