ch10-04 predict_manager.move 的用户账户和头寸管理
先看市场问题
这里先从市场定义往下看。“predict_manager.move 的用户账户和头寸管理”服务的是 Predict 市场如何被定义、定价、mint、settle 或索引;不要把它读成普通现货订单簿的变体。
源码入口
packages/predict/sources/predict_manager.move:PredictManager字段、deposit、withdraw、position 增减。packages/predict/sources/registry.move:创建和分享 manager 的入口与派生 key。packages/deepbook/sources/balance_manager.move:Predict 内部复用的余额模型。
关键定义
PredictManager 把用户余额和预测头寸放在一个共享对象里:
public struct PredictManagerKey(address, u64) has copy, drop, store;
public struct PredictManager has key {
id: UID,
owner: address,
balance_manager: BalanceManager,
deposit_cap: DepositCap,
withdraw_cap: WithdrawCap,
positions: Table<RangeKey, u64>,
}
公开给用户的资金入口:
public fun deposit<T>(self: &mut PredictManager, coin: Coin<T>, ctx: &TxContext)
public fun withdraw<T>(
self: &mut PredictManager,
amount: u64,
ctx: &mut TxContext,
): Coin<T>
包内头寸更新入口:
public(package) fun increase_position(self: &mut PredictManager, key: RangeKey, quantity: u64)
public(package) fun decrease_position(self: &mut PredictManager, key: RangeKey, quantity: u64)
positions 只保存区间数量,不保存成本价、手续费或 PnL。应用要展示收益,必须结合 mint/redeem 事件、交易 digest 或未来 Indexer 读模型。
读市场参数
PredictManager 是每个用户的共享对象,字段包括 owner、DeepBook BalanceManager、DepositCap、WithdrawCap 和 Table<RangeKey, u64> positions。registry.move::create_and_share_manager 使用 PredictManagerKey(address, 0) 派生对象 ID,v1 默认每个地址一个 manager。
用户资金先通过 deposit<T>(manager, coin, ctx) 进入内部 BalanceManager,交易时 predict.move 用包内权限调用 manager.withdraw<Quote>(cost, ctx)。头寸只记录 range quantity,不记录成本价;应用层要从事件、交易历史或未来 Indexer 里恢复成本和 PnL。
服务层通常提供 ensurePredictManager(owner):先按 PredictManagerKey(address, 0) 查询对象,不存在再构造创建 PTB。创建之后,后续 deposit、mint、redeem 都使用同一个 manager 对象,避免用户在多个 manager 间分散余额和头寸。
因为 positions table 只保存 quantity,成本价、fee、mint 时间和 realized PnL 需要从交易事件或未来 Indexer 读模型恢复。当前迁移状态下,应用可以本地记录提交摘要和 digest,但不能把未完成的 Predict Indexer 当成唯一账本。
Predict 边界判断
- manager 创建、deposit、mint 应拆成可组合 PTB,允许前端一次签名完成初始化。
- 任何交易都校验
ctx.sender()与 manager owner 一致,避免代签或错误对象。 - PnL 展示明确区分链上 position quantity 和链下成本记录。
动手检查
- 为什么 manager ID 派生要包含 owner,而 market key 不包含 owner?
- 如果用户换钱包或误选别人的 manager,Move 层会在哪里拒绝?
- 没有稳定 Indexer 时,应用如何保存和恢复用户成本信息?