Frontend APIs
Public endpoints, authentication, request and response fields, and wallet transactions. Detailed reference in Chinese. Polygon mainnet with test assets, not a real-funds release.
2026-09-16 全新部署接入:Polygon · 测试充值资产 · 真实 UMA。充值仅 mUSDT/mUSDC;USDC.e 仅用于 UMA 保证金。服务版本核验通过后开放交易,不提供旧开发版本入口。运行地址以合约目录的统一 SDK 清单为准。
线上环境
核对日期:2026-09-12。本文公开说明官网前端依赖的接口;不包含已下线游戏、管理后台接口、私钥、内部服务器地址或任何服务密钥。公共响应中的额外兼容字段不代表对应产品仍在开放。
| 项目 | 线上地址或状态 |
|---|---|
| Backend Base URL | https://wf.vip/backend |
| Indexer Base URL | https://wf.vip/indexer |
| 官网与 Next.js 接口 | https://wf.vip |
| 浏览器只读 RPC | https://polygon.drpc.org,钱包广播可以使用钱包自己的节点 |
| Deployment ID | polygon-mainnet-mock-standalone-v4-20260908 |
| 网络 | Polygon,chainId 137;mUSDT/mUSDC 测试资产,不代表真钱生产发布 |
| 启用产品 | Lotto3D、World Lotto UMA |
| 未启用产品 | BTC 5M/15M;相关调用在下文单独标注 |
例如代币列表完整地址为 https://wf.vip/backend/api/v1/tokens,3D 当前轮次为 https://wf.vip/indexer/lotto3d/current。不要漏掉 /backend 或 /indexer 前缀。
线上公开读取已核查;需要用户签名、充值授权、申请、账单修改或链上交易的写路径没有为发布文档而执行。请求/响应契约按已发布版本的对应实现核对,不将“路由存在”写成“全部资金流程已实测”。下文配置默认值和保留封装是排错参考,不是推荐使用本地地址接入。
1. 总览
| 类别 | 范围 | 调用方式 |
|---|---|---|
| Backend | 17 个业务接口:游戏状态、充值授权、钱包登录、通知、渠道申请和控制台 | 浏览器 HTTP JSON |
| Indexer | 当前产品相关查询及保留封装,见第 4 节;不含已下线游戏接口 | 浏览器只读 REST;不是 GraphQL |
| Next.js | 2 个 BTC 行情接口;另有 1 个健康检查 | 同站点 HTTP JSON |
| RPC | 链上读取、交易预执行、回执;另记录代码保留的 Backend RPC 网关 | JSON-RPC |
| 钱包/合约 | 充值、购票、领奖、提现和 SIWE 登录签名 | RainbowKit + wagmi/viem + 用户钱包 |
业务资金写入不是通过 Backend 的订单接口完成:购票直接调用 V4 Ledger,充值/提现调用 StablecoinReserve,领奖调用游戏或 Settlement 合约。Indexer 扫描链上事件供页面展示。
2. 地址、鉴权和数据约定
2.1 Base URL
后续 Backend 表格路径都拼接 BACKEND_API_BASE_URL;Indexer 表格路径都拼接 INDEXER_API_BASE_URL。
| 配置 | 默认值/来源 | 说明 |
|---|---|---|
NEXT_PUBLIC_BACKEND_API_BASE_URL | http://localhost:3001 | 路径仍包含 /api/v1/...;可设同源相对前缀 |
NEXT_PUBLIC_INDEXER_API_BASE_URL | http://localhost:42069 | 路径直接从 /ledger、/lotto3d 等开始,不统一带 /api/v1 |
NEXT_PUBLIC_RPC_GATEWAY_URL | 非空值优先;否则 ${BACKEND_API_BASE_URL}/api/v1/rpc | 变量名虽然叫 Gateway,也能填写直接 RPC 地址 |
NEXT_PUBLIC_PROTOCOL_V4_PURCHASES | 只有字符串 true 才启用 | 还要求 SDK 识别该游戏支持 V4 |
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID | 无默认凭证 | 配置后才提供 WalletConnect 等二维码连接;注入式钱包不需要 |
FRONTEND_BACKEND_PROXY_TARGET | 无默认值 | Next 服务端可将 /remote-backend/:path* 转给目标 Backend;不是自动代理全部 /api/v1 |
MARKET_SERVICE_URL | http://localhost:3010 | 仅 Next 服务端 BTC 报价路由使用 |
CHAINLINK_CANDLESTICK_API_URL | 可选 | 仅 Next 服务端 K 线路由使用 |
NEXT_PUBLIC_SETTLEMENT_API_BASE_URL | http://localhost:3002 | 存在配置常量,但当前前端没有直接调用 Settlement HTTP API |
| chainId、合约地址、功能开关 | @wf-protocol/contract-sdk / deployment manifest | 前端源码本身不写死另一套合约地址 |
NEXT_PUBLIC_* 会进入浏览器构建产物,不能放私钥或服务端密钥。本文不记录真实 RPC 凭证、API Key 或会话 Token。代码仍有 RPC 网关兜底;若部署要求直连,必须正确设置 RPC URL,不能仅凭产品要求推断当前环境已直连。线上地址以上方环境表为准,服务端私密 RPC 凭证不公开。
2.2 通用约定
| 类型/规则 | 约定 |
|---|---|
| POST JSON | Content-Type: application/json;通知标记接口无请求体 |
| 私有接口 | Authorization: Bearer <wallet-session-token>;只有会话退出、通知、Partner Console 需要 |
| 钱包地址 | 0x 加 40 位十六进制;服务端多处转小写存储/查询 |
| bytes32 | 0x 加 64 位十六进制;例如断言 ID、购票 Hash、公开渠道码 |
| uint 字符串 | 金额、区块、nonce、大整数 ID 使用十进制字符串;不要先转 JavaScript Number 再计算 |
| WUSD | 账本计量单位,6 位小数;1000000 = 1 WUSD;页面有时显示为 USD |
| ERC-20 金额 | 按 /api/v1/tokens 的 decimals 换算,不假定所有币种都与 WUSD 等精度 |
| BPS | 10000 = 100%;链上分佣池比例与 Web2 合作方二次分配比例是不同字段 |
| 链上时间 | Indexer 的 BigInt 时间输出 Unix 秒的十进制字符串 |
| Web2 时间 | Prisma 日期、generatedAt、expiresAt 等为 ISO 8601 字符串 |
| BTC K 线时间 | candles[].time 使用 Unix 毫秒,不是链上秒 |
| 空数据 | 多数单条 Indexer 查询返回 HTTP 200 + null;列表返回 [] 或空 items |
| 状态与最终性 | Indexer/BFF 是展示快照;交易是否成功看回执 status,业务是否合法以合约执行为准 |
没有统一的 { data, code, message } 成功包裹,必须按每个接口的返回结构读取。失败也不统一:Backend 常见 {error, code},钱包登录路由常仅有 {error},RPC 使用 JSON-RPC error。
3. Backend 接口清单
以下 17 个接口均有当前前端调用链。除注明外成功状态为 200。
| ID | 方法和路径 | 鉴权 | 用途及调用位置 |
|---|---|---|---|
| B01 | GET /api/v1/public/product-access | 无 | 地区/产品准入;lib/productAccess.tsx |
| B02 | GET /api/v1/public/games/state | 无 | 3D 游戏运行参数;useGameReadState |
| B03 | GET /api/v1/public/lotto-uma/snapshot | 无 | World Lotto 当前轮次聚合;useLottoUmaCurrentRound |
| B04 | GET /api/v1/public/lotto-uma/rounds/:roundId/source-plan | 无 | 七个主来源、两个替补和证据;useLottoUmaSourcePlan |
| B05 | GET /api/v1/tokens | 无 | 出入金代币选择;useWhitelistedTokens |
| B06 | POST /api/v1/deposit-authorizations | 无 Bearer;返回合约验签材料 | DepositPanel |
| B07 | POST /api/v1/wallet-auth/challenge | 无;要求合法 Origin | 取得钱包登录消息;walletAuth.tsx |
| B08 | POST /api/v1/wallet-auth/verify | 无;要求合法 Origin 和钱包签名 | 换取会话;walletAuth.tsx |
| B09 | DELETE /api/v1/wallet-auth/session | Bearer | 退出登录;walletAuth.tsx |
| B10 | GET /api/v1/notifications | Bearer | 通知列表;NotificationBell |
| B11 | POST /api/v1/notifications/:id/read | Bearer | 单条已读;NotificationBell |
| B12 | POST /api/v1/notifications/read-all | Bearer | 全部已读;NotificationBell |
| B13 | POST /api/v1/partner-applications | 无 | 申请合作;PartnerProgramPage |
| B14 | GET /api/v1/partner-console | Bearer | 当前钱包合作方成员资格;PartnerConsolePage |
| B15 | GET /api/v1/partner-console/:partnerId/purchases | Bearer + ACTIVE 成员 | 归因订单;PartnerConsolePage |
| B16 | GET /api/v1/partner-console/:partnerId/statements | Bearer + ACTIVE 成员 | 对账单;PartnerConsolePage |
| B17 | POST /api/v1/partner-console/:partnerId/statements/:statementId/decision | Bearer + ACTIVE OWNER/FINANCE | 确认/争议账单;PartnerConsolePage |
3.1 B01 产品准入
无查询参数,浏览器不自行指定国家。返回:
| 字段 | 类型 | 含义 |
|---|---|---|
policyVersion | string | 地区策略版本 |
mode | off / monitor / enforce | 执行模式 |
country | string/null | 服务端识别地区 |
source | string | 地区识别来源 |
products | object | 当前产品使用 lotto3d / lotto7uma / btc5m 的准入结果;其他兼容字段忽略 |
products[key].product | string | 产品代码 |
products[key].category | lottery / prediction | 类别 |
products[key].allowed / restricted | boolean | 是否允许/是否受限 |
products[key].reason | enum | available / monitor_only / restricted_region / country_unavailable |
products[key].serviceProvider | string | 服务提供方 |
products[key].protocolIndependent | true | 官网服务与公开协议独立 |
Cache-Control: private, no-store。前端 5 秒超时,未取得 allowed=true 不展示被准入边界包裹的参与操作。不能把准入接口返回值当成合约授权。
3.2 B02 游戏读取状态
无参数。当前前端使用的返回字段为 {deploymentId, source:"bff", lotto3d, generatedAt},忽略其他兼容字段。
| 对象 | 字段 |
|---|---|
lotto3d | paused:boolean;ticketPrice:string;carryPool:string,后两项为 WUSD 最小单位 |
当前 Backend 读取 3D 的 paused、ticketPrice 和 Treasury accumulatedPool。
失败:503 {error, code:"GAME_READ_STATE_UNAVAILABLE"}。
3.3 B03 World Lotto 聚合快照
无参数。无轮次返回 null,有轮次返回:
| 字段 | 类型/含义 |
|---|---|
deploymentId / source / generatedAt | string;source 固定 bff |
effectiveStatus | World Lotto 展示状态,见第 5 节 |
round | UmaRound,见第 5 节数据字典 |
drawRequest | UmaDrawRequest 或 null |
settlement | UmaSettlement 或 null |
paused | boolean,Rounds 合约暂停状态 |
carryPool | WUSD 整数字符串,Treasury currentCarryPool |
requiredBond | Oracle Adapter 保证金整数,使用保证金币种的 decimals,不直接当成 WUSD |
Backend 聚合 Indexer /lotto-uma/current 和三个合约读取;任一必需依赖失败可能返回 503 {error, code:"UMA_SNAPSHOT_UNAVAILABLE"}。前端没有在 BFF 失败时自动改读 Indexer current 的实现。
3.4 B04 来源计划和证据
路径 roundId 为十进制轮次 ID;实现仅接受 1~12 位数字且排除字符串 "0",不符合会走无计划结果。返回:
| 字段 | 类型/含义 |
|---|---|
roundId | string |
sourcePolicyVersion | number |
sourceConfigHash / sourceConfigUri | string,创建轮次所记录的来源配置 |
primarySources | string[7],按开奖位置排列 |
fallbackSources | string[2],替补顺序 |
actualSources | 数组;各项 {code:string,digit:string,unavailable:boolean,fallbackFor:string} |
evidence | string,断言操作记录中的证据内容;未提交可为空 |
数据来自 Backend 中状态为 EXECUTED 的创建轮次和 UMA 断言管理操作记录,不是前端读取链上国家列表。sourceConfigHash 存在不代表接口替调用方验证了证据内容。
无有效创建记录或不足 7+2 来源:404 {error,code:"SOURCE_PLAN_NOT_FOUND"},前端转为 null。服务异常:503 SOURCE_PLAN_UNAVAILABLE。公开缓存 30 秒。
3.5 B05 白名单代币
返回 {tokens:[{symbol:string,address:string,decimals:number}]}。地址来自当前配置;不要把 mUSDC/mUSDT 自动换成同名官方资产。只返回公开代币信息,不返回充值限额或风控内部阈值。
3.6 B06 充值授权
请求字段全部必填:
| 字段 | 类型 | 校验/含义 |
|---|---|---|
userAddress | address string | 本次实际向 Reserve 发交易的钱包 |
token | address string | 白名单 ERC-20 地址 |
amount | 十进制整数字符串 | 代币最小单位;调用方必须提交大于 0 的规范数字串 |
返回 {user,token,amount,deadline,nonce,signature},全部为 string;deadline 是 Unix 秒,signature 是服务端 EIP-712 签名。返回 amount 在签名结构里名为 authorizedAmount。
新部署处理过程:固定资产白名单 → 地址风险筛查 → nonce → 签名 → 授权审计记录。该接口不是充值交易,不会直接增加 WUSD。Reserve 无单笔或每日数量上限;后台是否仍返回旧额度错误必须在服务切换时核验。
| HTTP | code | 含义 |
|---|---|---|
| 400 | INVALID_REQUEST | 参数格式错误;可附 details 字段错误 |
| 400 | ZERO_AMOUNT | amount 为 "0" |
| 400 | TOKEN_NOT_WHITELISTED | 非白名单资产 |
| 403 | AML_REJECTED | 地址风险筛查拒绝 |
| 403 | EXCEEDS_SINGLE_TX_LIMIT / EXCEEDS_DAILY_LIMIT | 超过额度 |
| 503 | AML_ERROR | 筛查不可用,拒绝放行 |
| 429 | RATE_LIMITED | 每 IP 每分钟 10 次 |
| 500 | INTERNAL_ERROR | 未预期错误 |
当前路由格式正则为纯数字,零值快捷判断只匹配 "0";对接方不要用 "00" 等非规范写法依赖服务端纠正。链上仍会拒绝零额充值。
3.7 B07~B09 钱包登录
- POST challenge:请求
{address},地址必须合法,不接受多余字段;Origin必须在 Backend CORS 允许范围内。返回{id,message,expiresAt};id 为 UUID,消息为 SIWE,挑战 5 分钟有效。 - 钱包签署服务端原始
message。前端校验地址、站点 domain、URI、chainId、过期时间,不能自行改写消息。 - POST verify:请求
{id,signature};signature 为带0x的完整字节串,最长 8194 字符,不接受多余字段。返回{token,address,expiresAt},会话有效期 8 小时。 - 私有请求携带 Bearer token。该 token 是 64 位小写十六进制随机串,不是 JWT,也不是 partnerCode。
- DELETE session:无需请求体,返回
{ok:true}。缺失/失效 token 不视为成功注销。
挑战单次消费。前端 token 只存在 React 内存中;刷新页面、换账号、换链、换连接器、断开钱包都会失去本地登录会话。连接钱包不等于取得 Backend 登录身份。
错误:400 参数错误;401 挑战过期/已使用/签名无效;403 Origin 不允许;503 登录服务/RPC 不可用。登录路由组每 IP 每分钟 20 次,超限 429 使用限流中间件默认响应,不保证 JSON。私有接口通用鉴权错误为 WALLET_AUTH_REQUIRED 或 WALLET_AUTH_FAILED。
3.8 B10~B12 通知
GET 返回 {notifications,unreadCount},按 createdAt 倒序最多 50 条:
| 字段 | 类型 |
|---|---|
id / title / body / category | string |
titleEn / bodyEn / actionHref | string/null |
readAt | ISO 时间/null |
createdAt | ISO 时间 |
unreadCount 是这次返回的最多 50 条里的未读数,不是完整历史未读总数。读取列表时服务端会尝试同步自动通知,因此该 GET 不只是读取数据库。
单条已读:路径 id,空请求体,返回 {ok:true};非本人通知或不存在返回 404 NOTIFICATION_NOT_FOUND。全部已读:空请求体,返回 {ok:true,updated:number},会更新当前钱包全部未读通知,不限最近 50 条。
3.9 B13 合作方申请
以下除 payoutAddress 外全部必填,不接受额外字段:
| 字段 | 类型/约束 |
|---|---|
submissionToken | UUID;同一次表单重试使用同一个值 |
organizationName / productName | 去首尾空格后 2~120 字符 |
region / contactName | 去首尾空格后 2~80 字符 |
website | HTTP/HTTPS URL,最长 240 字符 |
businessEmail | email,最长 160 字符;服务端转小写 |
businessType | WALLET / COMMUNITY / MEDIA / GAME_PLATFORM / DATA_TOOL / OTHER |
monthlyUsers | UNDER_10K / 10K_100K / 100K_1M / OVER_1M |
targetRegions | 1~12 个字符串,每项 2~80 字符 |
integrationPlan | 20~2000 字符 |
payoutAddress | 可选 address 或空字符串;落库小写或 null |
locale | zh / en |
termsVersion | 1~32 字符 |
termsAccepted / complianceConfirmed | 必须为 true |
成功 201 {applicationNo,status},编号形如 WF-P-YYYYMMDD-XXXXXXXX。同 submissionToken 返回原申请,不覆盖已提交资料。新申请默认 SUBMITTED;审核状态还可能为 BUSINESS_REVIEW / RISK_REVIEW / TECHNICAL_VERIFICATION / APPROVED / REJECTED。
失败:400 INVALID_PARTNER_APPLICATION;429 PARTNER_APPLICATION_RATE_LIMITED,每 IP 每小时 5 次。此接口不返回 API Key,也不在提交时直接返回已批准的 partnerCode。当前前端没有申请查询或审核 API。
3.10 B14~B17 合作方控制台
partnerId 是数据库 Partner ID,不是公开渠道 code。partnerCode 不是登录凭证。
成员查询 B14:无参数,返回 {memberships:[{id,role,partner}]}。仅返回当前钱包 ACTIVE 成员关系,按成员创建时间升序。role 为 OWNER / FINANCE / VIEWER。partner 包含:
| 字段 | 类型/含义 |
|---|---|
id / code / name | string;code 为公开渠道归因码 |
status | ACTIVE / SUSPENDED / TERMINATED |
payoutAddress | string/null |
activatedAtBlock / disabledAtBlock | 十进制字符串/null |
createdAt / updatedAt | ISO 时间 |
commissionRates | 最近最多 20 个比例版本,version 倒序 |
statusVersions | 最近最多 20 个状态版本,version 倒序 |
_count | {chainPurchases:number,statements:number} |
版本对象共同字段:id,partnerId,version,effectiveFromBlock,effectiveToBlock,reason,createdBy,createdAt;区块为字符串,截止区块可为 null 且为开区间。佣金版本多 shareBps:number,状态版本多 status。
订单查询 B15:可选 query cursor,当前实现是从 0 开始的 offset,不是不透明游标;每次固定最多 100 条,按 blockNumber、logIndex 倒序。返回 {items,nextCursor};nextCursor 为字符串或 null。页面目前未消费 nextCursor,因此只显示第一批,并用这一批计算概览的已归因佣金,不能当成全历史累计。
每项订单返回 PartnerChainPurchase 的标量字段和 commission:
| 字段组 | 字段 |
|---|---|
| 标识/address/hash 字符串 | id,receiptId,wfOrderId,partnerCode,partnerId,owner,beneficiary,gameAddress,treasuryAddress,purchaseDataHash,submitter,txHash;partnerId 可空 |
| 整数字符串 | roundId,amount,purchaseNonce,blockNumber,blockTimestamp;amount 为 WUSD |
| number | chainId,allocationVersion,partnerBps,logIndex |
| 归因状态 | status: PARTNER_ATTRIBUTED / WF_DIRECT / HELD / REVERSED;reasonCode:string/null |
| 日期 | confirmedAt,createdAt,updatedAt;settledAt,lastValidatedAt,invalidatedAt 可空 |
| 佣金对象 | commission 为 null 或下述对象 |
commission 返回字段:
| 字段组 | 字段 |
|---|---|
| 标识 | id,chainPurchaseId,statementId,reserveBatchId,commissionRateId,sourceSettlementId;后四项可空 |
| WUSD 整数字符串 | finalNetAmount,grossCommissionAmount,commissionAmount,platformRemainderAmount,roundingRemainder |
| BPS 数字 | partnerBps 为链上总池比例;partnerShareBps 为合作方占总池比例 |
| 状态 | ESTIMATED / ELIGIBLE / STATEMENTED / PAID / REVERSED / HELD |
| 日期 | createdAt,updatedAt,eligibleAt;eligibleAt 可空 |
| 冲销 | reversal 为 null 或冲销对象 |
reversal 字段:id,commissionEntryId,partnerId,statementId,grossCommissionAmount,commissionAmount,platformRemainderAmount,reasonCode,evidenceBlock,evidenceTxHash,createdAt。金额为字符串;evidenceBlock 是字符串/null;statementId、evidenceTxHash 可空。
账单查询 B16:无分页参数,固定取 periodEnd 倒序最多 100 份,返回 {statements:[...]}。
| 字段组 | 字段 |
|---|---|
| 标识 | id,statementNo,partnerId,settlementKey,productCode,gameAddress |
| 周期/时间 | periodStart,periodEnd,settlementAt,createdAt,updatedAt,ISO 时间 |
| 比例 | baseCommissionBps,effectiveCommissionBps,number |
| 金额,均为 WUSD 字符串 | grossOrderAmount,grossCommissionAmount,platformCommissionAmount,openingBalance,openingPlatformBalance,accruedAmount,reversalAmount,adjustmentAmount,payableAmount,platformPayableAmount,paidAmount,platformPaidAmount |
| 状态 | DRAFT / ISSUED / CONFIRMED / DISPUTED / APPROVED / PAID / VOID |
| 可空字符串 | adminActionId,payoutTxHash,disputeReason |
| 可空时间 | issuedAt,confirmedAt,disputedAt,approvedAt,paidAt |
| 计数 | _count:{entries:number,reversals:number} |
账单决定 B17:body {action:"confirm"|"dispute",reason?:string}。reason 去首尾空格后最长 2000 字符,dispute 至少 10 字符。只允许 ISSUED 状态;confirm 后为 CONFIRMED,dispute 后为 DISPUTED。返回 {statement},标量字段同上,但不包含查询接口的 _count。
错误:403 PARTNER_CONSOLE_FORBIDDEN / PARTNER_STATEMENT_FORBIDDEN;400 INVALID_STATEMENT_DECISION;404 PARTNER_STATEMENT_NOT_FOUND;409 PARTNER_STATEMENT_STATE_CONFLICT;另有通用钱包鉴权错误。确认账单不是发起链上付款,页面不执行 Safe 打款。
4. Indexer REST 接口清单
本节都是 GET,无 Bearer。用户地址虽经页面登录/连接后才用于查询,服务端这些 REST 路由本身是公开链上数据查询。
P<T> 表示 {items:T[],page:number,pageSize:number,hasMore:boolean}。page 从 1 开始;服务端默认 pageSize=10,上限 50。前端封装默认轮次 6、票据历史 8;部分市场页显式传 8。没有 total 字段。调用方应传正整数;服务端用 Number 和范围夹取,并非所有非法格式都返回统一 400。
“保留”指没有当前页面调用链,不能作为已启用功能。编号保留原有引用,已下线游戏对应的编号不再列出。
| ID | 路径 | 参数 | 返回 | 调用/状态 |
|---|---|---|---|---|
| I01 | /activity/recent | limit,前端默认12,上限30 | {deploymentId,source:"ponder",items:Activity[]} | ActivityFeed、MarketVolumeChart |
| I02 | /ledger/balance/:user | 钱包地址 | {balance:string};无记录为 "0" | useLedgerAccount |
| I03 | /ledger/deposits/:user | 钱包地址 | Deposit[],时间倒序最多50 | useFundingHistory;另有未使用的 useDepositHistory |
| I04 | /ledger/withdrawals/:user | 钱包地址 | Withdrawal[],时间倒序最多50 | useFundingHistory |
| I05 | /users/:address/pending-prizes | 钱包地址 | PendingPrizes 对象 | usePendingPrizes |
| I06 | /v1/protocol/games/:game/rounds/:roundId/allocation | 游戏地址、轮次 | Allocation 对象 | 保留 roundRevenueAllocation 封装 |
| I14 | /lotto3d/rounds | page,pageSize,includeLatest | P<Lotto3dRound> | 历史/市场页;includeLatest 仅字符串 true 生效 |
| I15 | /lotto3d/current | 无 | Lotto3dRound/null | useLotto3dCurrentRound |
| I16 | /lotto3d/rounds/latest | 无 | Lotto3dRound/null | useLotto3dLatestRound 无页面引用 |
| I17 | /lotto3d/rounds/:roundId | 轮次 | Lotto3dRound/null | useLotto3dRound |
| I18 | /lotto3d/history/:buyer | 钱包 | Lotto3dTicketHistory[],最多100张 | useTicketHistory |
| I19 | /lotto3d/history/:buyer/page | 钱包;page,pageSize | P<Lotto3dTicketHistory> | GameHistoryLedger |
| I20 | /lotto-uma/current | 无 | {deploymentId,source,effectiveStatus,round,drawRequest,settlement} 或 null | 浏览器封装未用;Backend B03 确实依赖它 |
| I21 | /lotto-uma/rounds | page,pageSize | P<UmaRoundHistory> | 历史、市场页、首页 DrawStory;跳过最新轮 |
| I22 | /lotto-uma/rounds/:roundId | 轮次 | UmaRound/null | useLottoUmaRound |
| I23 | /lotto-uma/settlement/:roundId | 轮次 | UmaSettlement/null | useLottoUmaSettlement、DrawStory |
| I24 | /lotto-uma/draw-request/:assertionId | bytes32 | UmaDrawRequest/null | DrawStory;也有未挂载组件中的 Hook |
| I25 | /lotto-uma/ticket/:ticketId | 十进制票ID | UmaTicket/null | useLottoUmaTicket 无页面引用 |
| I26 | /lotto-uma/history/:buyer | 钱包 | UmaTicketHistory[],最多100张 | useTicketHistory |
| I27 | /lotto-uma/history/:buyer/page | 钱包;page,pageSize | P<UmaTicketHistory> | GameHistoryLedger |
4.1 特殊查询语义
I15 在最近 20 个轮次中优先选正在销售的 Open 轮次,其次最早即将开始的 Open 轮次,然后未解决的 Open/SalesClosed 轮次,最后才回退最新记录。它不等于最大 roundId。
I14 默认 includeLatest=false 跳过数据库最新一轮,true 不跳过。I21 固定跳过最新记录,不保证历史列表只含已开奖轮次。
I05 返回 {deploymentId,source:"ponder",address,hasPendingPrize,totalCount,games,items}。games 包含当前产品的 lotto3d、lotto7uma 计数,也可能包含兼容字段;items 为 {game,roundId,ticketId,tier,amount}。tier 为数字,amount 为 WUSD 字符串。该查询各游戏最多扫描 500 条购票记录,因此不是无限历史的完整资金审计 API。无效地址返回 400 {code:"INVALID_WALLET"}。
I06 的前端类型只声明 {allocationVersion,prizeBps,datBps,partnerBps,opsBps},均为 number。服务端还返回 id,gameKey,treasury,txHash 字符串,roundId,blockNumber,blockTimestamp 整数串,以及 deploymentId,indexedBlock,chainHead,finalityStatus,dataTimestamp 元数据;indexedBlock/chainHead 可空。它描述链上轮次资金分配,不是合作方最终 Web2 返佣比例;当前购票页不调用它。错误为400 INVALID_GAME_ADDRESS / INVALID_ROUND_ID,404 GAME_NOT_FOUND / ROUND_ALLOCATION_NOT_FOUND。
这里 finalityStatus 的实现是根据索引落后区块数推导的 finalized / pending / unknown 展示标签,不是对某笔交易不可重组的证明。
Indexer 前端客户端每次请求设置 8 秒超时。多数路由没有独立业务错误包装;不要假定所有非 2xx 返回同一种 JSON。活动接口有专门的 503 错误处理。字段缺失/null 和金额为零要分别处理。
5. Indexer 数据字典
下面“整数串”均指十进制 string;? 表示允许 null,而不是保证从 JSON 中省略。
5.1 公共活动和资金记录
| 对象 | 字段 |
|---|---|
| Activity | id:string,type:purchase|prize,game:string,roundId:整数串,user:address,amount:整数串?,tier:number?,count:number?,blockTimestamp:整数串,txHash:hash;当前产品 game 为 lotto3d / uma,其他历史游戏值应兼容处理 |
| Deposit | id,user,token,txHash 字符串;requestedAmount,receivedAmount,wusdCredited,nonce,blockNumber,blockTimestamp 整数串 |
| Withdrawal | id,user,token,recipient,txHash 字符串;wusdDebited,tokenAmount,blockNumber,blockTimestamp 整数串 |
充值 requestedAmount/receivedAmount 是原始币数量,wusdCredited 是账本入账;提现 wusdDebited 是账本扣款,tokenAmount 是外部币数量。两种余额不要相加作为同一个账户余额。
5.2 Lotto3dRound / Lotto3dTicketHistory
| 对象 | 字段/类型 |
|---|---|
| Lotto3dRound 标识/状态 | roundId:整数串;status:Open|SalesClosed|Settled|Cancelled |
| 时间和计数 | salesOpenTime,salesCloseTime,drawDeadline,totalSales,totalTickets,updatedAtBlock,updatedAtTimestamp:整数串 |
| 开奖和奖金 | winningNumber:number?;prizePool,prize1PerUnit,prize2PerUnit,prize3PerUnit,winUnits1,winUnits2,winUnits3:整数串? |
| Lotto3dTicket 基础 | ticketId,roundId,blockNumber,blockTimestamp:整数串;buyer,txHash:string;number:number;claimed,refunded:boolean |
| 历史扩展 | roundStatus:string?;roundWinningNumber:number?;roundTicketPrice:null;roundPayout1..3:整数串? |
3D 号码范围 0~999,展示补足三位。未开奖的 null 不能渲染成确定的 000。roundTicketPrice 当前固定 null,历史记录本身不提供真实票价快照。
5.3 UmaRound / UmaRoundHistory
| 字段组 | 字段/类型 |
|---|---|
| 标识和价格 | roundId,ticketPrice:整数串 |
| 布尔状态 | salesClosed,cancelled,hasHadAssertion |
| 时间 | salesOpenTime,salesCloseTime,drawDataDeadline,claimDeadline,assertionLiveness,drawResolvedAt,updatedAtBlock,updatedAtTimestamp:整数串 |
| 销售 | totalSales,totalUnits:整数串;maxMultiplierPerTicket:number |
| 号码 | winningNumber,winningNumberPreview:number?;preview 不代表最终开奖结果 |
| 证据和断言 | sourceBundleHash,normalizedDataHash,oracleAssertionId,oracleAdapter:string? |
drawStatus | None / PendingAssertion / ReadyForRetry / Drawn / Cancelled |
UmaRoundHistory 另有 status:string、sales:整数串、betCloseTime:整数串、prizePool:整数串?。历史奖池在存在结算时为各奖级 payout × winUnits 之和加 carryNext;无结算为 null,并非简单取销售额 80%。
B03/I20 的 effectiveStatus 可为:upcoming / betting_open / sales_close_overdue / awaiting_assertion / assertion_overdue / challenge_window / resolution_pending / disputed / ready_for_retry / awaiting_settlement / settled / cancelled。
这些是展示状态字符串,不是 Solidity 枚举数字。断言成立、开奖号码确定、奖金结算已发布分别是不同阶段。
5.4 UmaTicket / UmaTicketHistory / UmaSettlement / UmaDrawRequest
| 对象 | 字段 |
|---|---|
| UmaTicket | ticketId,roundId,number,paid,blockNumber,blockTimestamp:整数串;buyer,txHash:string;multiplier:number;claimed,refunded:boolean |
| UmaTicketHistory 扩展 | roundStatus:string;roundWinningNumber:number?;roundTicketPrice,roundPayout1..5:整数串? |
| UmaSettlement | roundId,payout1..5,winUnits1..5,carryNext,blockNumber,blockTimestamp:整数串;txHash:string |
| UmaDrawRequest | assertionId,sourceBundleHash,normalizedDataHash,asserter:string;roundId,winningNumber,assertedAt,updatedAtBlock,updatedAtTimestamp:整数串;resolvedTruthfully:boolean?;status 见下 |
UmaDrawRequest.status 为 Pending / ResolutionPending / Disputed / Abandoned / Resolved。World Lotto 号码 0~9999999,显示补足七位。Ticket/DrawRequest 的 number/winningNumber 在 Indexer 是字符串,而 Round 的 winningNumber 是 number/null,不要混用类型。
注意:当前 UmaSettlement REST 响应没有 claimDeadline 字段,虽然前端 mapSettlement 会读取并默认成 0。真正的领奖截止时间要从 UmaRound.claimDeadline 读取,不能将映射默认值当成服务端返回。
6. Next.js 接口与服务端上游
| ID | 方法和路径 | 请求 | 成功响应 | 失败 |
|---|---|---|---|---|
| N01 | GET /api/btc/candles | 无;前端固定请求 BTC 5m | {symbol,interval,source,candles,updatedAt} | 上游HTTP/格式问题502;异常503;{error} |
| N02 | GET /api/btc/quote | query outcome=yes|no,非 no 按 yes | {outcome,...quote,source:"wf-matcher",status:"ok"} | 无市场200 unavailable;异常503 unavailable |
| N03 | GET /api/health | 无 | {status:"ok",service:"frontend",deploymentId,generatedAt} | 健康检查,非页面业务调用 |
N01 每项 candle 为 {time,open,high,low,close,volume},均为 number,time 是毫秒。symbol 为 BTC/USD,interval 为 5m。优先请求配置的 Chainlink K 线 URL,成功但无有效数据或非成功 HTTP 时可继续用 Binance /api/v3/klines?symbol=BTCUSDT&interval=5m&limit=60。Chainlink fetch 直接抛异常时进入外层 503,不保证所有错误都会回退。
来源分别为 chainlink-candlestick 或 display-fallback-binance-btcusdt;Binance 只是显示兜底,不是协议最终结算来源。服务端内存缓存5秒,响应 public,max-age=5,stale-while-revalidate=15。
N02 服务端先 GET ${MARKET_SERVICE_URL}/v1/markets,选当前时间范围内 Open 市场,再 GET /v1/markets/:marketId/quote?tokenId=...。有效 quote 字段由上游透传,页面使用 bestBid:number|null、bestAsk:number|null、lastTrade:{price?:string}|null。接口未声明稳定的完整 quote DTO,调用方不能假定除此之外的字段永远存在。
无市场返回 {outcome,price:null,source:"wf-matcher",status:"unavailable"};异常响应另加 error。即使 HTTP 200,也必须看 status,不能直接认定有报价。
重要:BtcMarketData 当前在页面可见时每秒请求一次 K 线和 yes/no 两次报价,active=false 不停止请求。停用 Market 服务不代表浏览 BTC 页时不会调用这些接口。/btc15m 仅重定向到 /btc5m,没有独立 15M API。
7. RPC、钱包与链上接口
7.1 传输与交易确认
只读客户端使用配置的 RPC URL,支持 HTTP batch;Polygon 可经 Multicall3 合并读取。交易由用户连接的钱包处理,钱包可能使用自己的广播节点,不能保证写交易一定经过应用的只读 RPC。
| 能力 | 对应调用 |
|---|---|
| 钱包连接/账号读取 | RainbowKit 连接器、EIP-1193 provider;连接时通常请求账户权限,后续 getAddresses |
| 网络检查/切链 | getChainId、switchChain;钱包可能触发 wallet_switchEthereumChain/添加链流程 |
| 登录签名 | wagmi signMessageAsync,签署 SIWE 文本;不是购票 EIP-712 授权 |
| 合约读取/预执行 | readContract、simulateContract、publicClient.call,底层 eth_call |
| 广播交易 | sendTransaction,向钱包提交 to,data,value=0,通常对应 eth_sendTransaction |
| 确认交易 | waitForTransactionReceipt,回执状态必须 success;交易 Hash 本身不代表成功 |
交易过程:读取 nonce/准备 calldata → eth_call 预执行和钱包网络检查 → 用户确认 → 钱包返回 hash → 每2秒轮询回执。等待超时/查询失败后继续查询原 hash,不自动重发付款。仅加速(repriced)交易继续跟踪;取消或其他替换会提示核对钱包记录。同账号在本页面运行时串行处理,不能防止另一个标签页或外部客户端同时用 nonce。
7.2 链上只读方法
| 目标 | 方法 | 参数 | 返回/用途 | 调用方 |
|---|---|---|---|---|
| ERC-20 token | balanceOf(address) | 用户钱包或 Reserve 地址 | uint256;钱包余额/储备币余额 | DepositPanel、WithdrawPanel、BalanceOverview |
| ERC-20 token | allowance(address,address) | owner、Reserve | uint256;充值授权额度 | DepositPanel |
| UnifiedLedgerV4 | balanceOf(address) | 用户地址 | uint256 WUSD;写交易后/操作前刷新 | useLedgerAccount |
| UnifiedLedgerV4 | purchaseNonces(address) | owner | uint256;本次购票 nonce | useContractAction |
| StablecoinReserve | previewDeposit(address,uint256) | token、tokenAmount | uint256 WUSD | WithdrawPanel 用储备 token 余额估算可兑换 WUSD |
| StablecoinReserve | previewWithdraw(address,uint256) | token、wusdAmount | uint256 tokenAmount | WithdrawPanel 提现预估 |
paused/ticketPrice/currentCarryPool/accumulatedPool/requiredBond 等在本方案由 BFF 服务端读取,不是浏览器额外逐个调合约。余额日常来自 I02,显式刷新会读链并更新本地查询缓存。
7.3 充值写方法
先调用 ERC-20 approve(address Reserve,uint256 amount)(标准返回 bool),仅当 allowance 不足时执行,当前授权的是本次 amount,不是无限额度。成功后调用:
StablecoinReserve.deposit(token, amount, authorizedAmount, minWusdOut, deadline, nonce, signature)
| 参数 | Solidity 类型 | 当前前端来源 |
|---|---|---|
| token | address | B05 选择的代币 |
| amount | uint256 | 用户输入按 token.decimals 转换 |
| authorizedAmount | uint256 | B06 返回 amount |
| minWusdOut | uint256 | 当前前端直接填本次 amount |
| deadline / nonce | uint256 | B06 返回 |
| signature | bytes | B06 的服务端签名 |
合约 Solidity 返回 (received,wusdCredited);真实钱包发送接口先返回 tx hash,不直接返回 Solidity return value。最终入账参考链上 Deposited 事件和账本余额。
当前 minWusdOut=amount 依赖现有同精度、1:1资产配置;支持不同 decimals 或兑换率时不能照抄这个填法,应使用实际 WUSD 预估。文档记录现状,不声称前端已泛化所有代币。
授权 EIP-712 domain:name=WUSDStablecoinReserve,version=1,chainId=当前部署,verifyingContract=Reserve。类型 DepositAuthorization 字段严格按 user:address,token:address,authorizedAmount:uint256,deadline:uint256,nonce:uint256 排列。签名者是服务端,不是充值用户再签一次 typed data。
7.4 购票写方法
当前前端调用 UnifiedLedgerV4.executePurchaseV4(request,purchaseData),Solidity 返回 receiptId(bytes32),钱包返回 tx hash。调用者钱包必须对应 request.owner。
| request 字段 | Solidity 类型 | 当前生成规则 |
|---|---|---|
| owner | address | 当前钱包 |
| game | address | 游戏合约;World Lotto 为 Rounds,不是 Settlement |
| beneficiary | address | 缺省为当前钱包 |
| amount | uint256 | WUSD 总票款 |
| purchaseDataHash | bytes32 | keccak256(purchaseData) |
| wfOrderId | bytes32 | 封装支持传入;未传为 zeroHash |
| partnerCode | bytes32 | 封装支持公开渠道码;未传为 zeroHash |
| nonce | uint256 | 刚读取的 purchaseNonces(owner) |
| deadline | uint48 | 当前浏览器 Unix 秒 + 300 秒 |
当前 Lotto3D 和 World Lotto 购票面板未传 partnerCode/wfOrderId,因此默认都是 zeroHash,不会自动从网址解析渠道码。第三方协议支持的归因能力与本官网默认购买参数需要区分。
purchaseData 采用标准 ABI 编码,不是 packed:
| 游戏 | 类型顺序 | 值 |
|---|---|---|
| Lotto3D | uint40,uint16[] | roundId、三位号码数组 |
| World Lotto UMA | uint40,uint32[],uint16[] | roundId、七位号码数组、等长倍数数组 |
roundId 在 purchaseData 中,不是 request 元组独立字段。request 不包含 allocationVersion/partnerBps;它们由链上轮次配置决定。后台查询响应里仍有这些字段作为核算记录,不意味着用户要在购票时提交。
当前钱包模式不调用 executePurchaseWithAuthorizationV4、不申请 session key、不调用 Relayer,也没有每次购票的独立 EIP-712 签名步骤。用户每笔购买仍要确认一笔钱包交易并支付 Gas;登录一次不能替代每笔交易确认。
7.5 领奖/退款
| 游戏 | 合约目标/方法 | 参数 | 当前入口 |
|---|---|---|---|
| Lotto3D | Game claim(uint256 ticketId) | 全局 ticketId | account 页面 |
| World Lotto | Settlement claim(uint256 ticketId) | 全局 ticketId | account 页面;另有未挂载的 ClaimPanelUma 组件 |
不是向 Backend 提交领奖申请。成功奖金进入 WUSD 账本,提到外部钱包另走提现。World Lotto/3D 虽可从索引看到 refunded 状态,本次搜索未发现页面主动调用其退款合约函数;不能将“有退款索引”写成“已有完整退款按钮”。
7.6 提现写方法
StablecoinReserve.withdraw(token,wusdAmount,minTokenOut,recipient)
| 参数 | 类型/含义 |
|---|---|
| token | address,选择提取的白名单币种 |
| wusdAmount | uint256,6位小数账本金额 |
| minTokenOut | uint256,当前填 previewWithdraw 返回的 tokenAmount |
| recipient | address,用户明确确认的外部收款地址 |
前端检查账本余额、储备币余额和收款地址,调用 previewWithdraw 和 simulateContract,然后钱包发交易。无需另一次 ERC-20 approve,无提现 HTTP 授权接口。成功后账本扣款,Reserve 向 recipient 转币;仍受调用者余额、储备、授权、签名、minOut 和暂停约束;新 Reserve 无单笔或每日数量上限,废弃限额槽的 0 不代表禁止操作。Solidity 返回 uint256 tokenAmount,发送交易的前端仍先拿到 hash,通过回执和事件核实结果。
7.7 代码保留的 RPC 网关
只有 RPC URL 选到 Backend 时才使用 POST /api/v1/rpc。请求为标准 {jsonrpc:"2.0",id,method,params} 或1~50项数组。返回 result 或 {error:{code,message,data?}};RPC 方法错误可以是 HTTP 200,必须检查 JSON error。
该网关按配置限流,非法空/超50项 batch 返回400,超限429。服务方法白名单为只读/估算类(包括 eth_call、eth_getTransactionReceipt、eth_estimateGas 等),不支持用它代替钱包广播 eth_sendRawTransaction。本节只记录仓库仍存在的实现,不建议改变当前直连部署要求。
8. 用户完整调用路径
| 操作 | 顺序 |
|---|---|
| 打开官网 | B01准入 → 游戏BFF/Indexer快照 → 活动/轮次列表;无需先登录 |
| 连接钱包 | RainbowKit连接 → 检查链 → I02余额/I05待领奖/账户历史;钱包签名登录成功后进入账户;刷新通过会话校验恢复登录 |
| 登录通知/控制台 | B07 → 钱包SIWE签名 → B08 → 带Bearer读取B10或B14~16 |
| 充值 | B05 → ERC-20余额/allowance → B06 → 必要时approve → Reserve.deposit → 回执 → Ledger.balanceOf → I03索引历史 |
| 购买3D | B02 + I15/I17 → 核对余额 → purchaseNonces → 编码号码 → Ledger.executePurchaseV4 → 回执 → I18/I19显示票据 |
| 购买World Lotto | B03 + B04(选历史轮时I22)→ 核对余额 → purchaseNonces → Ledger.executePurchaseV4 → 回执 → I26/I27 |
| 查看开奖 | 3D读轮次;World Lotto读B03/I23/I24,区分断言、争议与最终结算 |
| 领奖 | I05或票据历史 → 对应claim → 回执 → 刷新历史/余额;索引可能稍后才追上 |
| 提现 | B05 + Ledger余额/Reserve储备 → previewWithdraw → simulateContract → withdraw → 回执 → I04和余额 |
| 合作方 | B13提交申请 → 后台审批及成员配置(不在本前端API范围)→ SIWE登录 → B14/B15/B16 → B17确认或争议 |
9. 刷新、边界与接入注意事项
| 查询 | 当前主要策略 |
|---|---|
| Product access | Provider挂载请求一次,5秒超时 |
| World Lotto B03 | 页面可见时15秒轮询 |
| 游戏状态、轮次详情、余额、资金历史 | 多数可见时20秒;以各Hook配置为准 |
| 来源计划B04 | staleTime30秒;不是每30秒主动轮询 |
| 待领奖I05 | 可见时30秒 |
| 通知 | 已登录且可见时30秒,并在恢复可见时刷新 |
| Partner Console | 加载/手动刷新/账单操作后刷新,没有自动获取全部分页 |
| BTC行情 | 可见时每秒三次HTTP请求,不受active=false阻止 |
| 交易回执 | 2秒轮询;查询失败后等待5秒继续,不重新付款 |
接入方需要特别区分:
- 登录成功、取得充值授权、钱包返回Hash、链上成功、Indexer出现记录、奖金结算完成是不同状态。
- “没有轮次”是合法空数据;接口错误不能伪装成余额为0或开奖结果为0。
- B03/I01等有 deploymentId,不是所有REST响应都包含该字段;上线需统一前后端/Indexer的部署配置,不能凭某个地址字段判断完全一致。
- 公共查询不要求 Partner API Key,Partner Console 则要求绑定钱包成员身份;公开归因码不能代替身份鉴权。
- Web2佣金份额由后台规则计算,前端既不提交最终返佣额,也不通过改写购票参数决定它。
- 当前查询带数量上限;完整财务历史导出不能直接使用页面已加载数组。
10. 不属于当前页面调用的接口
Backend bridge、管理后台/Safe审核、内部 Settlement任务、Indexer GraphQL/SQL以及 Indexer /v1/protocol/purchases/... 等更广泛协议接口,不在本前端运行时调用链中;本清单不将它们列为前端依赖。
没有发现当前页面通过业务 WebSocket、SSE 或 webhook 接收订单/返佣结果的实现。WalletConnect 的内部连接服务是钱包组件依赖,不是项目的订单 webhook。
没有新增或恢复 Partner API Key、Partner Order API、提交 txHash 接口;前端本地保存 hash 用于等待原交易回执,不等于要求第三方上报 hash。