从零起步,在imToken钱包中开发你的首个DApp

随着Web3生态的快速发展,imToken作为国内用户基数最大的去中心化钱包之一,支持以太坊、Polygon、BNB Chain等多条主流公链,为开发者提供了便捷的DApp接入渠道,无论你是区块链开发...

随着Web3生态的快速发展,imToken作为国内用户规模领先的去中心化钱包之一,支持以太坊、Polygon、BNB Chain等数十条主流公链,不仅为普通用户提供了安全易用的数字资产管理工具,也为开发者打通了直达海量Web3用户的便捷通道——无论是区块链开发新手,还是希望拓展业务的成熟团队,都可以通过imToken快速将DApp触达超千万的活跃用户,本文将带你一步步完成一个极简留言板DApp的开发、部署与imToken对接全流程,全程无需复杂的专业背景,新手也可以轻松上手。


前置准备:理清基础与开发环境

核心概念扫盲

针对Web3开发新手,我们先理清几个核心概念,方便后续理解开发流程:

  1. DApp:去中心化应用,由智能合约+前端界面两部分组成,核心数据全部存储在区块链上,无需依赖传统中心化服务器托管,用户通过钱包完成身份验证与交易签名,imToken内置了DApp浏览器,可以直接打开并交互你开发的DApp。
  2. 智能合约:运行在区块链上的自动化程序,是DApp的业务逻辑核心,本文将使用Solidity语言编写,这是以太坊生态最主流的智能合约开发语言。
  3. imToken对接方式:目前主流的两种对接方案:一是通过通用的WalletConnect协议实现钱包连接,无需额外开发复杂的钱包集成逻辑,适配绝大多数Web3钱包;二是使用imToken官方SDK,适合需要深度定制化交互的项目,对于新手来说WalletConnect是最简方案。

必备工具配置

安装并配置imToken钱包

从imToken官方网站下载正版钱包,创建或导入你的钱包账户。强烈建议全程使用测试网进行开发测试,避免主网操作失误带来真实资产损失。

添加测试网络并领取测试币

以最常用的Sepolia以太坊测试网为例:

  1. 打开imToken,进入「我的」-「设置」-「网络」,点击「添加自定义网络」
  2. 填入Sepolia测试网参数:
    • 网络名称:Sepolia Testnet
    • RPC URL:https://rpc.sepolia.org
    • 链ID:11155111
    • 符号:ETH
  3. 通过官方水龙头Sepolia Faucet领取免费测试币,用于支付合约部署与交易的Gas费。

    搭建开发环境

- 新手快速上手:直接使用[Remix在线IDE](https://remix.ethereum.org/),无需本地安装任何工具,在线完成合约编写、编译与部署
- 进阶项目开发:使用Hardhat、Foundry等本地开发框架,提升项目管理与测试效率

编写并部署留言板智能合约

我们将开发一个极简的留言板合约,实现用户发布留言、查看全量历史留言的基础功能,代码附带详细注释方便新手理解:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MessageBoard {
    // 定义留言结构体:记录发送者钱包地址、留言内容、留言上链时间戳
    struct Message {
        address sender;
        string content;
        uint256 timestamp;
    }
    // 存储所有用户留言的数组
    Message[] public messages;
    /**
     * @dev 发布留言的外部方法:将用户提交的留言写入区块链
     * @param _content 用户输入的留言内容
     */
    function postMessage(string calldata _content) external {
        messages.push(Message({
            sender: msg.sender, // 获取调用该方法的用户钱包地址
            content: _content,
            timestamp: block.timestamp // 获取当前区块的时间戳
        }));
    }
    /**
     * @dev 获取所有留言的视图方法:无需支付Gas费即可读取链上数据
     * @return 返回全部留言数组
     */
    function getMessages() external view returns (Message[] memory) {
        return messages;
    }
}

合约部署详细步骤

  1. 编写与编译合约:打开Remix在线IDE,新建MessageBoard.sol文件并粘贴上述代码,在左侧编译标签页选择8.0版本编译器,点击「Compile MessageBoard.sol」完成编译。
  2. 连接imToken钱包:切换到「部署与运行交易」标签页,在「环境」下拉框选择Injected Provider - MetaMask/imToken,此时会自动唤起imToken钱包,确认连接后即可完成IDE与钱包的绑定。
  3. 部署合约:在imToken中切换至Sepolia测试网,回到Remix页面点击「部署」按钮,在imToken中确认合约部署交易,等待数秒后交易上链成功,记录页面生成的合约地址,同时在编译标签页点击「ABI」按钮,复制合约的ABI接口描述,后续前端开发会用到。

对接imToken:实现前端交互

我们将通过极简的HTML+JS前端页面实现与智能合约的交互,无需复杂的前端框架,直接在浏览器中打开即可测试:

注意:以下代码存在一处小修正,原示例中HTML的title标签未闭合,已修复并补全完整交互逻辑。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">imToken 留言板DApp</title>
<!-- 引入WalletConnect钱包连接库 -->
<script src="https://unpkg.com/@walletconnect/web3-provider@1.8.0/dist/umd/index.min.js"></script>
<!-- 引入ethers.js,简化区块链交互逻辑 -->
<script src="https://cdn.jsdelivr.net/npm/ethers@5.7.2/dist/ethers.umd.min.js"></script>
<style>
body {max-width: 800px; margin: 0 auto; padding: 20px; font-family: Arial, sans-serif;}
textarea {width: 100%; height: 100px; margin: 10px 0; padding: 10px;}
button {padding: 10px 20px; margin: 5px; cursor: pointer;}
.message-item {border:1px solid #eee; padding:10px; margin:10px 0; border-radius: 8px;}
</style>
</head>
<body>
<h1>📝 imToken 留言板DApp</h1>
<button id="connectBtn">连接imToken钱包</button>
<div id="accountInfo" style="margin:10px 0; color:#666;"></div>
<textarea id="messageInput" placeholder="输入你的留言内容,支持中文和英文"></textarea>
<button id="postBtn">发布留言</button>
<h3>历史留言</h3>
<div id="messageList"></div>
<script>
    // ========== 请替换为你自己部署的合约地址和ABI ==========
    const CONTRACT_ADDRESS = "0xYourDeployedContractAddress";
    // 从Remix编译页面复制的ABI接口
    const ABI = [
        {"inputs":[{"internalType":"string","name":"_content","type":"string"}],"name":"postMessage","outputs":[],"stateMutability":"nonpayable","type":"function"},
        {"inputs":[],"name":"getMessages","outputs":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"string","name":"content","type":"string"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"internalType":"struct MessageBoard.Message[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"}
    ];
    let provider;
    let signer;
    let contractInstance;
    // 初始化页面:加载历史留言
    window.onload = async () => {
        await loadMessages();
    }
    // 连接imToken钱包
    document.getElementById("connectBtn").addEventListener("click", async () => {
        try {
            // 使用WalletConnect连接imToken
            provider = new WalletConnectProvider.default({
                rpc: { 11155111: "https://rpc.sepolia.org" },
                chainId: 11155111
            });
            await provider.enable();
            const ethersProvider = new ethers.providers.Web3Provider(provider);
            signer = ethersProvider.getSigner();
            const account = await signer.getAddress();
            document.getElementById("accountInfo").innerText = `✅ 已连接账户:${account}`;
            contractInstance = new ethers.Contract(CONTRACT_ADDRESS, ABI, signer);
            // 连接成功后加载最新留言
            await loadMessages();
        } catch (error) {
            alert("钱包连接失败:" + error.message);
        }
    });
    // 发布留言
    document.getElementById("postBtn").addEventListener("click", async () => {
        if (!contractInstance) {
            alert("请先连接imToken钱包");
            return;
        }
        const content = document.getElementById("messageInput").value.trim();
        if (!content) {
            alert("请输入留言内容");
            return;
        }
        try {
            // 调用合约的postMessage方法,发起交易
            const tx = await contractInstance.postMessage(content);
            await tx.wait(); // 等待交易上链
            alert("✅ 留言发布成功!");
            document.getElementById("messageInput").value = "";
            await loadMessages();
        } catch (error) {
            alert("发布失败:" + error.message);
        }
    });
    // 加载历史留言
    async function loadMessages() {
        if (!CONTRACT_ADDRESS || CONTRACT_ADDRESS === "0xYourDeployedContractAddress") {
            document.getElementById("messageList").innerHTML = "<p>请先部署合约并替换CONTRACT_ADDRESS</p>";
            return;
        }
        try {
            const messages = await fetch(`https://api-sepolia.etherscan.io/api?module=contract&action=getabi&address=${CONTRACT_ADDRESS}`)
            .then(res => res.json())
            .then(data => data.status === "1" ? contractInstance.getMessages() : []);
            const listDom = document.getElementById("messageList");
            if (messages.length === 0) {
                listDom.innerHTML = "<p>暂无留言,快来发布第一条吧!</p>";
                return;
            }
            listDom.innerHTML = "";
            // 倒序展示留言,最新的留言在最前面
            for (let i = messages.length - 1; i >= 0; i--) {
                const msg = messages[i];
                const time = new Date(msg.timestamp * 1000).toLocaleString();
                const item = document.createElement("div");
                item.className = "message-item";
                item.innerHTML = `
                    <div><strong>发送地址:</strong>${msg.sender}</div>
                    <div><strong>时间:</strong>${time}</div>
                    <div style="margin-top:8px;">${msg.content}</div>
                `;
                listDom.appendChild(item);
            }
        } catch (error) {
            document.getElementById("messageList").innerHTML = `<p>加载留言失败:${error.message}</p>`;
        }
    }
    // 监听钱包断开连接
    provider?.on("disconnect", () => {
        document.getElementById("accountInfo