构建一个简版Polymarket

Polymarket预测市场允许用户对未来的事件结果进行投注,不可变性确保了透明度。在本教程中,我们将从零开始构建一个简单版本的Polymarket。

构建一个简版Polymarket
一键发币: Aptos | X Layer | SUI | SOL | BNB | ETH | BASE | ARB | OP | Polygon | Avalanche | 用AI学区块链开发

在区块链中,预测市场允许用户对未来的事件结果进行投注,不可变性确保了透明度。这些市场通过 Polymarket 等平台获得了人气,尤其是在 2024 年美国总统选举期间。在本教程中,我们将从零开始构建一个简单的预测市场 dApp。

1、什么是预测市场?

预测市场是让用户购买未来事件潜在结果的股份的平台。每个预测市场包括:

  • 到期日期:市场关闭且不再接受购买股份的日期
  • 问题:被预测的事件(例如,“比特币明天会达到 10 万美元吗?”)
  • 选项:用户可以下注的可能结果(例如,“是”或“否”)

我们的项目采用一种固定模型,其中:

  • 每股成本正好为 1 个代币
  • 赢家的股份将从输家的股份池中分配

例如,如果用户购买了 12 股 A 选项和 6 股 B 选项,并且 A 选项正确,那么 A 选项的每股市值将获得 B 选项池中的 0.5 股额外股份。

更复杂的预测市场如 Polymarket 使用一种订单簿模型,类似于股票交易,价格根据市场需求波动。

2、构建我们的预测市场智能合约

我们将创建一个简单的 Solidity 智能合约,处理以下功能:

  1. 创建带有问题和选项的市场
  2. 购买结果的股份
  3. 在结果已知时解决市场
  4. 为下注正确结果的用户领取奖金
合约的关键组件
// 合约结构与关键市场数据
enum MarketOutcome { Unresolved, OptionA, OptionB }

struct Market {
    string question;
    string optionA;
    string optionB;
    uint256 endTime;
    MarketOutcome outcome;
    uint256 totalOptionAShares;
    uint256 totalOptionBShares;
    bool resolved;
    mapping(address => uint256) optionABalances;
    mapping(address => uint256) optionBBalances;
    mapping(address => bool) hasClaimed;
}

该合约使用自定义的 ERC20 代币进行购买,我们将单独部署它。关键函数包括:

  • createMarket: 只有所有者可以创建新的市场
  • buyShares: 市场未过期时任何人都可以购买股份
  • resolveMarket: 所有者在市场过期后解决市场
  • claimWinnings: 用户在下注正确结果时领取他们的奖励

3、构建网络界面

我们将创建一个 Next.js 应用程序,使用 thirdweb 的 SDK 与我们的智能合约交互,包括:

  1. 显示按状态(活动、待定、已解决)过滤的市场仪表板
  2. 显示当前股份分布的市场卡片
  3. 购买股份的 UI
  4. 从已解决市场中领取奖励的功能

3.1 设置 thirdweb 集成

首先,我们在 Next.js 应用程序中配置 thirdweb:

// src/app/client.ts
import { createThirdwebClient } from "thirdweb";

export const client = createThirdwebClient({
  clientId: process.env.NEXT_PUBLIC_THIRDWEB_CLIENT_ID as string,
});

我们还设置合同包装器以轻松与我们的智能合约交互:

// src/constants/contract.ts
export const contractAddress = "0x124D803F8BC43cE1081110a08ADd1cABc5c83a3f";
export const tokenAddress = "0x4D9604603527322F44c318FB984ED9b5A9Ce9f71";

export const contract = getContract({
    client: client,
    chain: baseSepolia,
    address: contractAddress
});

3.2 实现用户认证

我们集成 thirdweb 的 ConnectButton 与智能账户抽象和气体赞助,使用户能够使用熟悉的 Web2 方法登录:

<ConnectButton 
    client={client} 
    theme={lightTheme()}
    chain={baseSepolia}
    connectButton={{
        label: 'Sign In',
    }}
    wallets={[
        inAppWallet(),
    ]}
    accountAbstraction={{
        chain: baseSepolia,
        sponsorGas: true,
    }}
/>

这种方法通过以下方式消除了新用户的复杂性:

  • 让他们使用电子邮件、密钥或社交账户登录
  • 自动创建智能钱包
  • 赞助气体费用,因此用户不需要 ETH 来参与

3.3 构建市场卡片组件

MarketCard 组件是我们的 UI 的核心,显示:

  • 市场问题和到期日期
  • 当前的股份分布
  • 购买股份的界面
  • 用户当前的股份和潜在收益

我们使用 thirdweb 的钩子来从智能合约中获取数据:

// 获取市场数据
const { data: marketData } = useReadContract({
    contract,
    method: "function getMarketInfo(uint256 _marketId) view returns (string question, string optionA, string optionB, uint256 endTime, uint8 outcome, uint256 totalOptionAShares, uint256 totalOptionBShares, bool resolved)",
    params: [BigInt(index)]
});

3.4 实现股份购买流程

我们的股份购买流程包括:

  1. 选择一个选项
  2. 输入要购买的股份数量
  3. 批准代币支出(如果需要)
  4. 确认购买
// 处理股份购买事务
const handleConfirm = async () => {
    setIsConfirming(true);
    try {
        const tx = await prepareContractCall({
            contract,
            method: "function buyShares(uint256 _marketId, bool _isOptionA, uint256 _amount)",
            params: [BigInt(marketId), selectedOption === 'A', BigInt(toWei(amount.toString()))]
        });
        await mutateTransaction(tx);

        // 显示成功提示
        toast({
            title: "购买成功!",
            description: `您购买了 ${amount} ${selectedOption === 'A' ? market.optionA : market.optionB} 股份`,
        })

        handleCancel();
    } catch (error) {
        console.error(error);
    } finally {
        setIsConfirming(false);
    }
};

3.5 添加代币领取功能

为了简化演示,我们实现了一个“领取代币”按钮,通过 thirdweb Engine 将预测代币铸造到用户的钱包中:

// 处理代币领取 API 调用
const handleClaimTokens = async () => {
    setIsClaimLoading(true);
    try {
        const resp = await fetch("/api/claimToken", {
            method: "POST",
            body: JSON.stringify({ address: account?.address }),
        });

        if (!resp.ok) {
            throw new Error('领取代币失败');
        }

        toast({
            title: "代币已领取!",
            description: "您的代币已成功领取。",
        });
    } catch (error) {
        console.error(error);
    } finally {
        setIsClaimLoading(false);
    }
};

4、最终应用功能

我们完成的预测市场 dApp 包括:

  1. 用户认证
  • 基于 Web2 的登录,使用智能钱包
  • 用户无需支付 gas 费(赞助交易)
  1. 市场仪表板
  • 正在接受下注的活跃市场
  • 等待解决的待定市场
  • 用户可以领取奖励的已解决市场
  1. 市场互动
  • 购买结果的股份
  • 查看当前市场分布
  • 从获胜的下注中领取奖励
  1. 代币管理
  • 通过 thirdweb Engine 铸造演示代币
  • 批准代币支出以进行购买

5、结束语

这个简单的预测市场展示了如何使用 thirdweb 将智能合约与用户友好的网页界面结合。该应用程序处理市场创建、股份购买、市场解决和奖励分发——这些都是预测市场的核心功能。

通过使用账户抽象和气体赞助,我们消除了新用户进入的重大障碍,让他们专注于参与预测市场,而不是管理钱包和气体费用。

您可以查看完整的源代码并构建自己的预测市场,访问 GitHub 仓库

该项目作为一个基础,可以扩展更多高级功能,如多选项市场、可变定价模型,或与真实世界数据预言机集成以实现自动市场解决。


原文链接:Building a Simple Prediction Market dApp with thirdweb

DefiPlot翻译整理,转载请标明出处

免责声明:本站资源仅用于学习目的,也不应被视为投资建议,读者在采取任何行动之前应自行研究并对自己的决定承担全部责任。