DApp 开发入门指南

DApp 开发入门指南 🔨

1. DApp 基础概念

1.1 什么是 DApp?

去中心化应用(DApp)是基于区块链的应用程序,特点是:

  • 后端运行在区块链网络
  • 前端可以是任何框架
  • 使用智能合约处理业务逻辑
  • 数据存储在区块链上

1.2 DApp 架构

复制代码
前端 (Web/Mobile)
    ↕️
Web3 接口层
    ↕️
智能合约层
    ↕️
区块链网络

2. 开发环境搭建

2.1 基础工具安装

bash 复制代码
# 安装 Node.js 和 npm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
nvm install node

# 安装 Hardhat
npm install --save-dev hardhat

# 安装 Web3.js 或 Ethers.js
npm install web3
# 或
npm install ethers

2.2 项目初始化

bash 复制代码
# 创建新项目
mkdir my-dapp
cd my-dapp

# 初始化项目
npm init -y
npx hardhat init

# 安装前端依赖
npm install react react-dom
npm install @web3-react/core @web3-react/injected-connector

3. 智能合约开发

3.1 合约示例

solidity 复制代码
// contracts/TodoList.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract TodoList {
    struct Task {
        uint id;
        string content;
        bool completed;
    }
    
    mapping(uint => Task) public tasks;
    uint public taskCount;
    
    event TaskCreated(uint id, string content);
    event TaskCompleted(uint id, bool completed);
    
    function createTask(string memory _content) public {
        taskCount++;
        tasks[taskCount] = Task(taskCount, _content, false);
        emit TaskCreated(taskCount, _content);
    }
    
    function toggleCompleted(uint _id) public {
        Task memory _task = tasks[_id];
        _task.completed = !_task.completed;
        tasks[_id] = _task;
        emit TaskCompleted(_id, _task.completed);
    }
}

3.2 合约测试

javascript 复制代码
// test/TodoList.test.js
const { expect } = require("chai");

describe("TodoList", function() {
    let TodoList;
    let todoList;
    let owner;
    
    beforeEach(async function() {
        TodoList = await ethers.getContractFactory("TodoList");
        [owner] = await ethers.getSigners();
        todoList = await TodoList.deploy();
        await todoList.deployed();
    });
    
    it("Should create a new task", async function() {
        await todoList.createTask("Test task");
        const task = await todoList.tasks(1);
        expect(task.content).to.equal("Test task");
    });
});

4. 前端开发

4.1 React 组件示例

jsx 复制代码
// src/components/TodoList.js
import { useState, useEffect } from 'react';
import { ethers } from 'ethers';
import TodoList from '../artifacts/contracts/TodoList.sol/TodoList.json';

const TodoListComponent = () => {
    const [tasks, setTasks] = useState([]);
    const [newTask, setNewTask] = useState('');
    const [contract, setContract] = useState(null);
    
    useEffect(() => {
        const init = async () => {
            if (window.ethereum) {
                const provider = new ethers.providers.Web3Provider(window.ethereum);
                const signer = provider.getSigner();
                const contract = new ethers.Contract(
                    CONTRACT_ADDRESS,
                    TodoList.abi,
                    signer
                );
                setContract(contract);
                loadTasks(contract);
            }
        };
        init();
    }, []);
    
    const loadTasks = async (contract) => {
        const taskCount = await contract.taskCount();
        const loadedTasks = [];
        for (let i = 1; i <= taskCount; i++) {
            const task = await contract.tasks(i);
            loadedTasks.push(task);
        }
        setTasks(loadedTasks);
    };
    
    const createTask = async () => {
        if (!newTask) return;
        try {
            const tx = await contract.createTask(newTask);
            await tx.wait();
            setNewTask('');
            loadTasks(contract);
        } catch (error) {
            console.error("Error creating task:", error);
        }
    };
    
    return (
        <div>
            <h1>Todo List</h1>
            <input
                value={newTask}
                onChange={(e) => setNewTask(e.target.value)}
                placeholder="New task..."
            />
            <button onClick={createTask}>Add Task</button>
            <ul>
                {tasks.map(task => (
                    <li key={task.id.toString()}>
                        {task.content}
                        {task.completed ? " ✓" : ""}
                    </li>
                ))}
            </ul>
        </div>
    );
};

export default TodoListComponent;

4.2 Web3 集成

javascript 复制代码
// src/utils/web3.js
import { InjectedConnector } from '@web3-react/injected-connector';
import { Web3Provider } from '@ethersproject/providers';

export const injected = new InjectedConnector({
    supportedChainIds: [1, 3, 4, 5, 42]
});

export const getLibrary = (provider) => {
    const library = new Web3Provider(provider);
    library.pollingInterval = 12000;
    return library;
};

5. IPFS 集成

5.1 文件存储

javascript 复制代码
import { create } from 'ipfs-http-client';

const ipfs = create({ host: 'ipfs.infura.io', port: 5001, protocol: 'https' });

async function uploadToIPFS(file) {
    try {
        const added = await ipfs.add(file);
        const url = `https://ipfs.infura.io/ipfs/${added.path}`;
        return url;
    } catch (error) {
        console.error('Error uploading file: ', error);
    }
}

5.2 元数据存储

javascript 复制代码
async function saveMetadata(data) {
    const metadata = JSON.stringify(data);
    try {
        const added = await ipfs.add(metadata);
        return added.path;
    } catch (error) {
        console.error('Error saving metadata: ', error);
    }
}

6. 部署和维护

6.1 部署脚本

javascript 复制代码
// scripts/deploy.js
async function main() {
    const TodoList = await ethers.getContractFactory("TodoList");
    const todoList = await TodoList.deploy();
    await todoList.deployed();
    
    console.log("TodoList deployed to:", todoList.address);
}

main()
    .then(() => process.exit(0))
    .catch(error => {
        console.error(error);
        process.exit(1);
    });

6.2 监控和维护

javascript 复制代码
// 事件监听
contract.on("TaskCreated", (id, content) => {
    console.log(`New task created: ${content} (ID: ${id})`);
    updateUI();
});

// 错误处理
function handleError(error) {
    if (error.code === 4001) {
        console.log('Transaction rejected by user');
    } else if (error.code === -32603) {
        console.log('Internal JSON-RPC error');
    }
    // 处理其他错误...
}

7. 最佳实践

7.1 安全考虑

  1. 输入验证
  2. 权限控制
  3. 重入攻击防护
  4. Gas 优化

7.2 用户体验

  1. 交易等待提示
  2. 错误友好提示
  3. 离线功能支持
  4. 响应式设计

8. 相关资源

相关推荐
大飞pkz10 分钟前
【Lua】题目小练12
开发语言·lua·题目小练
赵得C16 分钟前
Java 多线程环境下的全局变量缓存实践指南
java·开发语言·后端·spring·缓存
nightunderblackcat40 分钟前
新手向:Python编写简易翻译工具
开发语言·python
打不过快跑1 小时前
YOLO 入门实战(二):用自定义数据训练你的第一个检测模型
人工智能·后端·python
站大爷IP1 小时前
Python网络爬虫在环境保护中的应用:污染源监测数据抓取与分析
python
EndingCoder1 小时前
Electron 简介:Node.js 桌面开发的起点
开发语言·前端·javascript·electron·node.js·桌面端
m0_480502642 小时前
Rust 登堂 之 类型转换(三)
开发语言·后端·rust
郏国上2 小时前
如何循环同步下载文件
开发语言·javascript·node.js