You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用JavaScript对接Solidity拍卖智能合约 实现NFT市场DApp拍卖功能

前端JS调用SimpleAuction合约实现指南

前置准备

调用合约前你需要先拿到两个核心信息,再安装对应依赖:

  • 把你提供的SimpleAuction合约编译后部署到测试链(如Sepolia)或本地测试网,拿到合约部署地址和合约ABI(编译输出的JSON数组)
  • 前端安装链交互依赖,这里以常用的ethers.js V6为例,执行npm install ethers即可,也可以用CDN直接引入

小提示:你提供的合约里有个拼写小错误,报错提示There is alreay a higher or equal bid中的alreay应为already,不影响核心功能,可修改后重新部署。

核心实现步骤

1. 初始化钱包连接与合约实例

首先要触发用户钱包连接(如MetaMask),拿到签名器后初始化可读可写的合约实例:

import { ethers } from "ethers";

// 替换为你自己的合约部署地址
const AUCTION_CONTRACT_ADDRESS = "0x你部署后的合约地址";
// 替换为你编译合约得到的完整ABI,这里只列核心方法的ABI片段供参考
const AUCTION_ABI = [
    "function bid() public payable",
    "function withdraw() public returns (bool)",
    "function auctionEnd() public",
    "function highestBid() public view returns (uint)",
    "function highestBidder() public view returns (address)",
    "function auctionEndTime() public view returns (uint)",
    "event HighestBidIncrease(address bidder, uint amount)",
    "event AuctionEnded(address winner, uint amount)"
];

async function initAuctionContract() {
    if (!window.ethereum) throw new Error("请先安装MetaMask钱包");
    // 请求用户连接钱包
    await window.ethereum.request({ method: "eth_requestAccounts" });
    const provider = new ethers.BrowserProvider(window.ethereum);
    const signer = await provider.getSigner();
    // 初始化可读可写的合约实例
    return new ethers.Contract(AUCTION_CONTRACT_ADDRESS, AUCTION_ABI, signer);
}

2. 调用合约可写方法

调用bid()方法出价

async function placeBid(bidAmountInEth) {
    const auctionContract = await initAuctionContract();
    // 把输入的ETH金额转为wei单位
    const bidAmountWei = ethers.parseEther(bidAmountInEth.toString());
    try {
        // payable方法需要传入value参数指定发送的原生币金额
        const tx = await auctionContract.bid({ value: bidAmountWei });
        // 等待交易上链确认
        await tx.wait();
        alert("出价成功");
    } catch (err) {
        console.error("出价失败:", err);
        alert(err.reason || "出价失败,请检查金额是否高于当前最高价、拍卖是否已结束");
    }
}

调用withdraw()方法提取退回的资金

async function withdrawRefund() {
    const auctionContract = await initAuctionContract();
    try {
        const tx = await auctionContract.withdraw();
        await tx.wait();
        alert("退款提取成功");
    } catch (err) {
        console.error("提取失败:", err);
        alert("提取失败,请确认你有可退回的未中标资金");
    }
}

调用auctionEnd()方法结束拍卖

async function endAuction() {
    const auctionContract = await initAuctionContract();
    try {
        const tx = await auctionContract.auctionEnd();
        await tx.wait();
        alert("拍卖已结束,资金已划转至受益人地址");
    } catch (err) {
        console.error("结束拍卖失败:", err);
        alert(err.reason || "结束失败,请检查拍卖是否已到结束时间、是否已经执行过结束操作");
    }
}

3. 读取合约公开状态数据

只读操作不需要用户签名,用provider初始化合约实例即可:

async function getAuctionBaseInfo() {
    if (!window.ethereum) throw new Error("请先安装MetaMask钱包");
    const provider = new ethers.BrowserProvider(window.ethereum);
    const auctionContract = new ethers.Contract(AUCTION_CONTRACT_ADDRESS, AUCTION_ABI, provider);
    // 批量读取合约状态
    const [highestBid, highestBidder, auctionEndTime] = await Promise.all([
        auctionContract.highestBid(),
        auctionContract.highestBidder(),
        auctionContract.auctionEndTime()
    ]);
    // 单位转换适配前端展示
    return {
        highestBidEth: ethers.formatEther(highestBid),
        highestBidder: highestBidder,
        endTime: new Date(Number(auctionEndTime) * 1000).toLocaleString(),
        isEnded: Date.now() > Number(auctionEndTime) * 1000
    };
}

4. 监听合约事件实现实时更新

可以监听合约抛出的事件,不用轮询就能实时更新前端状态:

async function listenAuctionEvents() {
    const auctionContract = await initAuctionContract();
    // 监听新的最高出价事件
    auctionContract.on("HighestBidIncrease", (bidder, amount) => {
        const bidEth = ethers.formatEther(amount);
        console.log(`新出价:地址${bidder} 出价${bidEth}ETH`);
        // 这里写你更新前端出价展示的逻辑
    });
    // 监听拍卖结束事件
    auctionContract.on("AuctionEnded", (winner, amount) => {
        const winEth = ethers.formatEther(amount);
        console.log(`拍卖结束,胜者为${winner},出价${winEth}ETH`);
        // 这里写你更新拍卖结束状态的逻辑
    });
}

调试注意事项

  • 开发阶段优先在测试链调试,确认功能无问题后再部署到主网
  • 所有涉及原生币转账的参数,注意单位转换,合约默认接收的是wei,不要直接传ETH数值
  • 合约抛出的revert错误信息可以直接从err.reason中获取,直接展示给用户即可
  • 如果你使用Web3.js作为交互库,核心逻辑一致,仅API写法有差异,按对应库的文档调整即可

内容的提问来源于stack exchange,提问作者aliekber1976

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 14:00:04