以太坊开发入门,从零开始构建你的第一个DApp
以太坊作为全球领先的智能合约平台,不仅仅是一种加密货币,更是一个去中心化的应用(DApp)生态系统,它为开发者提供了强大的工具和框架,使得构建和部署去中心化应用成为可能,本教程将带你踏以太坊开发的学习之旅,从基础概念到实践操作,一步步引导你构建你的第一个DApp。
以太坊开发基础:你需要了解什么?
在开始编码之前,我们需要理解几个核心概念:
- 区块链与以太坊:区块链是一种分布式账本技术,以太坊则是基于区块链技术的开源平台,它允许开发者编写和部署智能合约。
- 智能合约:智能合约是运行在以太坊虚拟机(EVM)上的自执行代码,它们在满足预设条件时自动执行合约条款,是不可篡改和透明的,可以理解为“在区块链上运行的自动化的、可信任的程序”。
- 以太坊虚拟机(EVM):EVM是以太坊的核心,它是一个图灵完备的虚拟机,能够执行任何复杂的智能合约代码,所有兼容以太坊的区块链都能运行EVM,确保了生态的互操作性。
- 账户(Accounts):以太坊有两种账户:外部账户(EOA,由用户私钥控制,如你的钱包)和合约账户(由代码控制),账户之间通过交易进行交互。
- Gas:为了防止网络滥用和补偿计算资源,以太坊网络中的每笔操作和智能合约执行都需要支付Gas,Gas是衡量计算工作量的单位,用ETH支付。
- Solidity:是最流行的智能合约编程语言,其语法类似于JavaScript,我们将主要使用Solidity来编写合约。
开发环境搭建
准备好开发环境是以太坊开发的第一步:
- 安装Node.js和npm:Node.js是一个JavaScript运行时,npm是Node.js的包管理器,从官网nodejs.org下载并安装LTS版本。
- 安装Truffle Suite:Truffle是以太坊最受欢迎的开发框架之一,它提供了开发、测试和部署智能合约的一整套工具。
npm install -g truffle
- 安装Ganache:Ganache是一个个人以太坊区块链,用于快速部署和测试合约,它提供了一个图形界面,可以实时查看交易和合约状态,你可以从Ganache官网下载,或者使用其命令行版本。
npm install -g ganache-cli
- 安装MetaMask:MetaMask是一个浏览器插件钱包,可以让你与以太坊区块链(包括测试网络)进行交互,管理账户,并与DApp进行交互,从MetaMask官网安装并设置。
- 代码编辑器:推荐使用Visual Studio Code(VS Code),并安装Solidity相关插件,如“Solidity by Juan Blanco”。
创建你的第一个以太坊项目(使用Truffle)
-
初始化项目: 创建一个新的项目文件夹,并在其中初始化Truffle项目:
mkdir my-first-dapp cd my-first-dapp truffle init
这会生成一些标准目录结构:
contracts/(存放智能合约)、migrations/(部署脚本)、test/(测试文件)等。 -
编写智能合约: 打开
contracts目录,删除默认的Migrations.sol,创建一个新的合约文件,例如SimpleStorage.sol:// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract SimpleStorage { uint256 private storedData; function set(uint256 x) public { storedData = x; } function get() public view returns (uint256) { return storedData; } }这个合约非常简单,包含一个
set函数用于存储一个无符号整数,和一个get函数用于读取这个整数。 -
编写迁移脚本: 打开
migrations目录,创建一个新的迁移脚本文件,例如2_deploy_simple_storage.js:const SimpleStorage = artifacts.require("SimpleStorage"); module.exports = function (deployer) { deployer.deploy(SimpleStorage); };这个脚本告诉Truffle如何部署我们的
SimpleStorage合约。 -
启动Ganache: 打开Ganache,确保选择“QUICKSTART”模式,它会启动一个本地私有区块链,并提供你10个测试账户,每个账户都有100个测试ETH。
-
配置Truffle连接Ganache: 在项目根目录下创建或修改
truffle-config.js文件(如果truffle init没生成的话),配置网络以连接到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) }, }, compilers: { solc: { version: "0.8.0", // Fetch exact version from solc-bin (default: truffle's version) } } };
注意端口号(7545)要与你Ganache中显示的端口一致。
-
编译合约: 在项目根目录的终端中运行:
truffle compile
如果成功,你会在
build/contracts目录下看到编译后的合约JSON文件。 -
部署合约: 运行以下命令部署合约到Ganache:
truffle migrate --network development
你会看到Ganache界面中出现了新的交易记录,部署成功后,
build/contracts/SimpleStorage.json中会包含合约的部署地址。
与你的智能合约交互
-
创建前端界面: 在项目根目录下创建一个
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>Simple Storage DApp</title> <script src="https://cdn.ethers.io/lib/ethers-5.2.umd.min.js" type="application/javascript"></script></head> <body> <h1>Simple Storage DApp</h1> <div> <label for="valueInput">Set Value:</label> <input type="number" id="valueInput" placeholder="Enter a number"> <button onclick="setValue()">Set</button> </div> <div> <button onclick="getValue()">Get Value</button> <p>Current Value: <span id="currentValue">0</span></p> </div> <script src="app.js"></script> </body> </html>app.js:let contract; const contractAddress = "YOUR_CONTRACT_ADDRESS_HERE"; // 替换为部署合约时得到的地址 const contractABI = [/* 这里粘贴SimpleStorage的ABI */]; // 稍后从编译后的JSON中获取 // 初始化 ethers const provider = new ethers.providers.Web3Provider(window.ethereum); const signer = provider.getSigner(); async function init() { // 请求用户授权连接钱包 await window.ethereum.request({ method: 'eth_requestAccounts' }); // 连接到合约 contract = new ethers.Contract(contractAddress, contractABI, signer); getValue(); } async function setValue() { const valueInput = document.getElementById("valueInput"); const value = valueInput.value; if (value) { try { const tx = await contract.set(value); await tx.wait(); alert("Value set successfully!"); getValue(); } catch (error) { console.error(error); alert("Error setting value"); } } } async function getValue() { try { const value = await contract.get(); document.getElementById("currentValue").textContent = value.toString(); } catch (error) { console.error(error); alert("Error getting value"); } } // 页面加载完成后初始化 window.addEventListener('load', init);注意:你需要将
YOUR_CONTRACT_ADDRESS_HERE替换为实际部署的合约地址,并将contractABI替换为SimpleStorage.json中的abi数组,你可以从build/contracts/SimpleStorage.json中复制ABI。 -
**启动前端
上一篇: 探索OE官网,开启优质体验的官方入口