在区块链开发中,DApp(去中心化应用)的开发往往涉及到多个层次:前端、合约和后端。今天我们将演示如何将 Vue 前端、Hardhat 合约 和 Node.js 后端 放在一个项目中,来打造一个完整的区块链应用。
1. 项目结构
我们的目标是创建一个 Monorepo 项目,将所有代码放在同一个仓库里。这样有助于我们统一管理依赖、版本,并能方便地实现前后端协作。
项目的结构如下:
my-dapp-project/
│
├── contracts/ # Hardhat 合约代码
│ ├── MyContract.sol
│ ├── hardhat.config.js
│ └── ...
│
├── scripts/ # Hardhat 部署与交互脚本
│ ├── deploy.js
│ └── ...
│
├── test/ # Hardhat 测试代码
│
├── frontend/ # Vue 前端
│ ├── src/
│ ├── public/
│ ├── package.json
│ └── vite.config.js
│
├── backend/ # 后端服务(Node.js / Express / NestJS 等)
│ ├── src/
│ ├── package.json
│ └── server.js
│
├── shared/ # (可选)前后端共享代码/类型
│ └── contract-types/
│
├── package.json # 根目录 package.json(可用来管理全部子项目依赖)
├── README.md
└── .gitignore
2. 环境搭建
首先,我们需要初始化项目的根目录并安装相关依赖。
2.1 初始化根目录
mkdir my-dapp-project
cd my-dapp-project
npm init -y
2.2 安装 Hardhat
npm install --save-dev hardhat
npx hardhat init
2.3 创建 Vue 前端
我们将在 frontend/
文件夹中创建 Vue 项目。使用 Vue CLI 来创建前端应用:
cd frontend
npm init vue@latest
npm install
2.4 创建 Node.js 后端
在 backend/
文件夹中,我们将创建一个简单的 Node.js 服务来处理后端逻辑:
cd backend
npm init -y
npm install express ethers
在 backend/src/server.js
中,我们会创建一个简单的 Express 服务来监听和处理合约事件。
3. 编写合约
我们将创建一个简单的智能合约 MyContract.sol
,它包含一个简单的存取款功能。
3.1 创建 contracts/MyContract.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MyContract {
uint256 public balance;
function deposit(uint256 amount) public {
balance += amount;
}
function withdraw(uint256 amount) public {
require(amount <= balance, "Insufficient funds");
balance -= amount;
}
}
3.2 部署合约
在 scripts/deploy.js
文件中,我们编写部署脚本:
const hre = require("hardhat");
async function main() {
const [deployer] = await hre.ethers.getSigners();
console.log("Deploying contracts with the account:", deployer.address);
const MyContract = await hre.ethers.getContractFactory("MyContract");
const contract = await MyContract.deploy();
console.log("MyContract deployed to:", contract.address);
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
部署合约后,我们将得到合约地址,并将其传递给前端和后端。
4. 后端与智能合约交互
在后端,我们将使用 ethers.js
连接到区块链,并提供一些 API 来让前端调用智能合约。
4.1 创建后端 server.js
const express = require('express');
const { ethers } = require('ethers');
const app = express();
const port = 3000;
// 连接到以太坊节点
const provider = new ethers.JsonRpcProvider('http://localhost:8545');
// 智能合约 ABI 和地址
const abi = [
"function deposit(uint256 amount) public",
"function balance() public view returns (uint256)"
];
const contractAddress = 'YOUR_CONTRACT_ADDRESS_HERE';
// 创建合约实例
const contract = new ethers.Contract(contractAddress, abi, provider);
app.get('/balance', async (req, res) => {
const balance = await contract.balance();
res.json({ balance: balance.toString() });
});
app.post('/deposit', express.json(), async (req, res) => {
const { amount } = req.body;
const signer = provider.getSigner();
const contractWithSigner = contract.connect(signer);
await contractWithSigner.deposit(amount);
res.json({ message: 'Deposit successful' });
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
在这个简单的 Node.js 后端中,我们提供了 /balance
和 /deposit
API,用于查询余额和执行存款操作。
5. 前端与后端交互
在前端,我们将使用 ethers.js
连接到智能合约,并调用合约方法。同时,我们也会通过 API 与后端进行交互。
5.1 安装 ethers.js
cd frontend
npm install ethers
5.2 Vue 前端调用合约
在 Vue 中,我们可以通过 ethers.js
调用智能合约。以下是一个简单的 Vue 组件示例,展示如何与智能合约交互:
<template>
<div>
<h1>Balance: {{ balance }}</h1>
<button @click="deposit">Deposit 10</button>
</div>
</template>
<script>
import { ethers } from 'ethers';
export default {
data() {
return {
balance: 0,
contract: null,
};
},
async mounted() {
const provider = new ethers.JsonRpcProvider('http://localhost:8545');
const abi = [
"function deposit(uint256 amount) public",
"function balance() public view returns (uint256)"
];
const contractAddress = 'YOUR_CONTRACT_ADDRESS_HERE';
this.contract = new ethers.Contract(contractAddress, abi, provider);
this.updateBalance();
},
methods: {
async updateBalance() {
this.balance = await this.contract.balance();
},
async deposit() {
const signer = this.contract.provider.getSigner();
const contractWithSigner = this.contract.connect(signer);
await contractWithSigner.deposit(10);
this.updateBalance();
}
}
};
</script>
6. 启动项目
// 1. 启动本地链:
npx hardhat run scripts/deploy.js --network localhost
// 2. 部署合约:
npx hardhat run scripts/deploy.js --network localhost
// 3. 启动后端服务
cd backend
node src/server.js
// 4. 启动前端服务:
cd frontend
npm run dev
总结
通过将 Vue 前端、Hardhat 合约 和 Node.js 后端 放在同一个项目中,我们可以方便地管理所有代码和依赖,创建一个完整的去中心化应用(DApp)。在这个示例中,前端与后端通过智能合约交互,后端提供了一些 API 来简化与合约的通信。
这个结构不仅适用于简单的 DApp 项目,也可以扩展到更复杂的应用,支持更多的区块链交互、API 处理和前端功能。