Skip to content

Pool 模块

模块路径: coinfair_clmm::pool

Pool 模块是整个 Coinfair DEX 的核心模块,实现了类似 Uniswap V3 的集中流动性机制。本版本实现了统一费用收取机制,所有费用都从代币B收取。

View 方法(只读)

get_pool_tokens

获取池子的代币类型。

move
#[view]
public fun get_pool_tokens(pool_address: address): (Object<Metadata>, Object<Metadata>)

参数:

  • pool_address: address - 池子地址

返回: (Object<Metadata>, Object<Metadata>) - (代币A元数据, 代币B元数据)


get_fee_rate

获取池子费率。

move
#[view]
public fun get_fee_rate(pool_address: address): u64

参数:

  • pool_address: address - 池子地址

返回: u64 - 池子费率(分子,分母为1_000_000)


is_pool_paused

检查池子是否暂停。

move
#[view]
public fun is_pool_paused(pool_address: address): bool

参数:

  • pool_address: address - 池子地址

返回: bool - 池子是否暂停


get_current_tick_index

获取当前tick索引。

move
#[view]
public fun get_current_tick_index(pool_address: address): I64

参数:

  • pool_address: address - 池子地址

返回: I64 - 当前tick索引


get_fee_growth_global

获取全局费用增长率。

move
#[view]
public fun get_fee_growth_global(pool_address: address): (u128, u128)

参数:

  • pool_address: address - 池子地址

返回: (u128, u128) - (代币A全局费用增长率, 代币B全局费用增长率)(Q64.64格式)


get_protocol_fees

获取协议费用。

move
#[view]
public fun get_protocol_fees(pool_address: address): (u64, u64)

参数:

  • pool_address: address - 池子地址

返回: (u64, u64) - (代币A协议费用, 代币B协议费用)


get_pool_balances

获取池子余额。

move
#[view]
public fun get_pool_balances(pool_address: address): (u64, u64)

参数:

  • pool_address: address - 池子地址

返回: (u64, u64) - (代币A余额, 代币B余额)


get_pool_info

获取完整的池子信息。

move
#[view]
public fun get_pool_info(pool_address: address): PoolInfo

参数:

  • pool_address: address - 池子地址

返回: PoolInfo - 完整的池子信息(包含所有已初始化的tick)

PoolInfo 结构:

move
struct PoolInfo {
    index: u64,
    collection_name: String,
    metadata_a: Object<Metadata>,
    metadata_b: Object<Metadata>,
    tick_spacing: u64,
    fee_rate: u64,
    liquidity: u128,
    current_fifrt_price: u128,
    current_tick_index: I64,
    fee_growth_global_a: u128,
    fee_growth_global_b: u128,
    fee_protocol_coin_a: u64,
    fee_protocol_coin_b: u64,
    rewarder_infos: vector<Rewarder>,
    rewarder_last_updated_time: u64,
    position_index: u64,
    is_pause: bool,
    uri: String,
    initialized_ticks: vector<Tick>
}

get_position_count

获取位置总数。

move
#[view]
public fun get_position_count(pool_address: address): u64

参数:

  • pool_address: address - 池子地址

返回: u64 - 位置总数


get_collection_name

获取位置NFT集合名称。

move
#[view]
public fun get_collection_name(pool_address: address): String

参数:

  • pool_address: address - 池子地址

返回: String - 位置NFT集合名称


get_pool_uri

获取池子URI。

move
#[view]
public fun get_pool_uri(pool_address: address): String

参数:

  • pool_address: address - 池子地址

返回: String - 池子URI


get_rewarder_last_updated_time

获取奖励器最后更新时间。

move
#[view]
public fun get_rewarder_last_updated_time(pool_address: address): u64

参数:

  • pool_address: address - 池子地址

返回: u64 - 奖励器最后更新时间(Unix时间戳)


get_rewarder_info

获取奖励器信息。

move
#[view]
public fun get_rewarder_info(
    pool_address: address,
    index: u8
): (Object<Metadata>, address, address, u128, u128)

参数:

  • pool_address: address - 池子地址
  • index: u8 - 奖励器索引(0-2)

返回: (Object<Metadata>, address, address, u128, u128) - (奖励代币元数据, 权限地址, 待转移权限地址, 每秒发放数量, 全局奖励增长率)


position_exists

检查位置是否存在。

move
#[view]
public fun position_exists(pool_address: address, position_index: u64): bool

参数:

  • pool_address: address - 池子地址
  • position_index: u64 - 位置索引

返回: bool - 位置是否存在


get_position_liquidity

获取位置流动性。

move
#[view]
public fun get_position_liquidity(pool_address: address, position_index: u64): u128

参数:

  • pool_address: address - 池子地址
  • position_index: u64 - 位置索引

返回: u128 - 位置流动性数量


get_position_fees_owed

获取位置待收取费用。

move
#[view]
public fun get_position_fees_owed(
    pool_address: address,
    position_index: u64
): (u64, u64)

参数:

  • pool_address: address - 池子地址
  • position_index: u64 - 位置索引

返回: (u64, u64) - (代币A待收取费用, 代币B待收取费用)


get_position_rewards_owed

获取位置待收取奖励。

move
#[view]
public fun get_position_rewards_owed(
    pool_address: address,
    position_index: u64
): vector<u64>

参数:

  • pool_address: address - 池子地址
  • position_index: u64 - 位置索引

返回: vector<u64> - 各奖励器的待收取奖励数量向量(按奖励器索引顺序)


get_position

获取完整的位置信息。

move
#[view]
public fun get_position(
    pool_address: address,
    pos_index: u64
): Position

参数:

  • pool_address: address - 池子地址
  • pos_index: u64 - 位置索引

返回: Position - 完整的位置信息

Position 结构:

move
struct Position {
    pool: address,
    index: u64,
    liquidity: u128,
    tick_lower_index: I64,
    tick_upper_index: I64,
    fee_growth_inside_a: u128,
    fee_owed_a: u64,
    fee_growth_inside_b: u128,
    fee_owed_b: u64,
    rewarder_infos: vector<PositionRewarder>
}

get_position_tick_range

获取位置的tick范围。

move
#[view]
public fun get_position_tick_range(
    pool_address: address,
    position_index: u64
): (I64, I64)

参数:

  • pool_address: address - 池子地址
  • position_index: u64 - 位置索引

返回: (I64, I64) - (下边界tick, 上边界tick)


get_user_positions

查询用户在某个池子里的所有位置索引。

move
#[view]
public fun get_user_positions(
    pool_address: address,
    user_address: address
): vector<u64>

参数:

  • pool_address: address - 池子地址
  • user_address: address - 用户地址

返回: vector<u64> - 用户拥有的所有位置索引向量

说明: 通过检查用户是否持有对应的位置NFT来判断位置所有权


get_user_positions_detail

查询用户在某个池子里的所有位置详细信息。

move
#[view]
public fun get_user_positions_detail(
    pool_address: address,
    user_address: address
): vector<Position>

参数:

  • pool_address: address - 池子地址
  • user_address: address - 用户地址

返回: vector<Position> - 用户拥有的所有位置的完整信息向量

说明: 通过检查用户是否持有对应的位置NFT来判断位置所有权,并返回完整的Position数据


fetch_ticks

分页获取池子中的tick数据。

move
#[view]
public fun fetch_ticks(
    pool_address: address,
    index: u64,
    offset: u64,
    limit: u64
): (u64, u64, vector<Tick>)

参数:

  • pool_address: address - 池子地址
  • index: u64 - 起始索引组
  • offset: u64 - 起始偏移量
  • limit: u64 - 获取数量限制

返回: (u64, u64, vector<Tick>) - (下一个索引组, 下一个偏移量, tick数据向量)


fetch_positions

分页获取池子中的位置数据。

move
#[view]
public fun fetch_positions(
    pool_address: address,
    index: u64,
    limit: u64
): (u64, vector<Position>)

参数:

  • pool_address: address - 池子地址
  • index: u64 - 起始位置索引
  • limit: u64 - 获取数量限制

返回: (u64, vector<Position>) - (下一个索引, 位置数据向量)


calculate_swap_result

计算交换结果(不实际执行交换)。

move
#[view]
public fun calculate_swap_result(
    pool_address: address,
    a2b: bool,
    by_amount_in: bool,
    amount: u64
): CalculatedSwapResult

参数:

  • pool_address: address - 池子地址
  • a2b: bool - 交换方向(true: A换B, false: B换A)
  • by_amount_in: bool - 按输入量还是输出量计算(true为按输入量,false为按输出量)
  • amount: u64 - 交换数量

返回: CalculatedSwapResult - 计算出的交换结果

CalculatedSwapResult 结构:

move
struct CalculatedSwapResult {
    amount_in: u64,                      // 计算的输入代币数量
    amount_out: u64,                     // 计算的输出代币数量
    fee_amount: u64,                     // 计算的交易费用
    fee_rate: u64,                       // 使用的费率
    after_fifrt_price: u128,             // 交换后的价格平方根
    is_exceed: bool,                     // 是否超出了价格限制
    step_results: vector<SwapStepResult> // 每一步的交换结果详情
}

SwapStepResult 结构:

move
struct SwapStepResult {
    current_fifrt_price: u128,           // 当前步骤开始时的价格平方根
    target_fifrt_price: u128,            // 目标价格平方根
    current_liquidity: u128,              // 当前步骤的流动性
    amount_in: u64,                       // 该步骤的输入数量
    amount_out: u64,                      // 该步骤的输出数量
    fee_amount: u64,                      // 该步骤的费用
    remainer_amount: u64                  // 剩余未处理的数量
}

get_tick_spacing

获取池子的tick间距。

move
#[view]
public fun get_tick_spacing(pool: address): u64

参数:

  • pool: address - 池子地址

返回: u64 - tick间距


get_fifrt_price

获取当前fifrt价格。

move
#[view]
public fun get_fifrt_price(pool: address): u128

参数:

  • pool: address - 池子地址

返回: u128 - 当前fifrt价格(Q64.64格式)


get_pool_liquidity

获取池子总流动性。

move
#[view]
public fun get_pool_liquidity(pool: address): u128

参数:

  • pool: address - 池子地址

返回: u128 - 池子总流动性


get_pool_index

获取池子索引。

move
#[view]
public fun get_pool_index(pool: address): u64

参数:

  • pool: address - 池子地址

返回: u64 - 池子索引


get_rewarder_len

获取奖励器数量。

move
#[view]
public fun get_rewarder_len(pool_address: address): u8

参数:

  • pool_address: address - 池子地址

返回: u8 - 奖励器数量(最多3个)


Public 方法(可写)

open_position

开启新的流动性位置。

move
public fun open_position(
    account: &signer,
    pool_address: address,
    tick_lower_index: I64,
    tick_upper_index: I64
): u64

参数:

  • account: &signer - 位置所有者
  • pool_address: address - 池子地址
  • tick_lower_index: I64 - 下边界tick(有符号整数)
  • tick_upper_index: I64 - 上边界tick(有符号整数)

返回: u64 - 位置索引

前置条件:

  • tick_lower < tick_upper
  • tick值必须是tick_spacing的倍数

事件: 触发 OpenPositionEvent

关联: 自动铸造位置NFT


add_liquidity

向位置添加指定数量的流动性。

move
public fun add_liquidity(
    pool_address: address,
    liquidity: u128,
    position_index: u64
): AddLiquidityReceipt

参数:

  • pool_address: address - 池子地址
  • liquidity: u128 - 要添加的流动性数量
  • position_index: u64 - 位置索引

返回: AddLiquidityReceipt - 添加流动性收据(热土豆模式,必须立即处理)

AddLiquidityReceipt 结构:

move
struct AddLiquidityReceipt {
    pool_address: address,
    amount_a: u64,
    amount_b: u64
}

注意: 需要调用 repay_add_liquidity 完成操作

事件: 触发 AddLiquidityEvent


add_liquidity_fix_coin

通过固定一种代币的数量来添加流动性。

move
public fun add_liquidity_fix_coin(
    pool_address: address,
    amount: u64,
    fix_amount_a: bool,
    position_index: u64
): AddLiquidityReceipt

参数:

  • pool_address: address - 池子地址
  • amount: u64 - 固定的代币数量
  • fix_amount_a: bool - true表示固定代币A,false表示固定代币B
  • position_index: u64 - 位置索引

返回: AddLiquidityReceipt - 添加流动性收据

注意: 需要调用 repay_add_liquidity 完成操作


repay_add_liquidity

支付代币完成流动性添加。

move
public fun repay_add_liquidity(
    asset_a: FungibleAsset,
    asset_b: FungibleAsset,
    receipt: AddLiquidityReceipt
)

参数:

  • asset_a: FungibleAsset - 代币A资产
  • asset_b: FungibleAsset - 代币B资产
  • receipt: AddLiquidityReceipt - 添加流动性收据

前置条件: 代币数量必须与收据要求一致


remove_liquidity

从位置移除流动性。

move
public fun remove_liquidity(
    account: &signer,
    pool_address: address,
    liquidity: u128,
    position_index: u64
): (FungibleAsset, FungibleAsset)

参数:

  • account: &signer - 位置所有者
  • pool_address: address - 池子地址
  • liquidity: u128 - 要移除的流动性数量
  • position_index: u64 - 位置索引

返回: (FungibleAsset, FungibleAsset) - (代币A资产, 代币B资产)

前置条件: 必须是位置所有者

事件: 触发 RemoveLiquidityEvent


checked_close_position

关闭空位置(流动性为0)。

move
public fun checked_close_position(
    account: &signer,
    pool_address: address,
    position_index: u64
): bool

参数:

  • account: &signer - 位置所有者
  • pool_address: address - 池子地址
  • position_index: u64 - 位置索引

返回: bool - 是否成功关闭

前置条件: 位置流动性必须为0

事件: 触发 ClosePositionEvent

关联: 自动销毁位置NFT


collect_fee

收集位置累积的交易费用。

move
public fun collect_fee(
    account: &signer,
    pool_address: address,
    position_index: u64,
    update_reward: bool
): (FungibleAsset, FungibleAsset)

参数:

  • account: &signer - 位置所有者
  • pool_address: address - 池子地址
  • position_index: u64 - 位置索引
  • update_reward: bool - 是否同时更新奖励

返回: (FungibleAsset, FungibleAsset) - (代币A费用, 代币B费用)

事件: 触发 CollectFeeEvent


collect_rewarder

收集位置累积的流动性挖矿奖励。

move
public fun collect_rewarder(
    account: &signer,
    pool_address: address,
    position_index: u64,
    rewarder_index: u8,
    update_reward: bool
): FungibleAsset

参数:

  • account: &signer - 位置所有者
  • pool_address: address - 池子地址
  • position_index: u64 - 位置索引
  • rewarder_index: u8 - 奖励器索引(0-2)
  • update_reward: bool - 是否更新奖励状态

返回: FungibleAsset - 奖励代币资产

事件: 触发 CollectRewardEvent


collect_protocol_fee

收集池子累积的协议费用。

move
public fun collect_protocol_fee(
    account: &signer,
    pool_address: address
): (FungibleAsset, FungibleAsset)

参数:

  • account: &signer - 协议费用领取权限账户
  • pool_address: address - 池子地址

返回: (FungibleAsset, FungibleAsset) - (代币A协议费用, 代币B协议费用)

前置条件: 必须是协议费用领取权限账户

事件: 触发 CollectProtocolFeeEvent


flash_swap

执行闪电交换(先获得输出,后支付输入)。

move
public fun flash_swap(
    pool_address: address,
    swap_from: address,
    a2b: bool,
    by_amount_in: bool,
    amount: u64,
    fifrt_price_limit: u128
): (FungibleAsset, FungibleAsset, FlashSwapReceipt, u64)

参数:

  • pool_address: address - 池子地址
  • swap_from: address - 交换发起者地址
  • a2b: bool - true表示A换B,false表示B换A
  • by_amount_in: bool - true表示amount是输入数量,false表示是输出数量
  • amount: u64 - 交换数量
  • fifrt_price_limit: u128 - 价格限制(防止滑点过大)

返回:

  • FungibleAsset - 输出代币A(如果a2b则为零)
  • FungibleAsset - 输出代币B(如果!a2b则为零)
  • FlashSwapReceipt - 交换收据(热土豆模式)
  • u64 - 推荐费用数量

FlashSwapReceipt 结构:

move
struct FlashSwapReceipt {
    pool_address: address,
    a2b: bool,
    pay_amount: u64
}

注意: 需要调用 repay_flash_swap 完成支付

事件: 触发 SwapEvent


repay_flash_swap

支付代币完成闪电交换。

move
public fun repay_flash_swap(
    asset_a: FungibleAsset,
    asset_b: FungibleAsset,
    receipt: FlashSwapReceipt
)

参数:

  • asset_a: FungibleAsset - 代币A资产(a2b时包含支付金额)
  • asset_b: FungibleAsset - 代币B资产(!a2b时包含支付金额)
  • receipt: FlashSwapReceipt - 闪电交换收据

swap_pay_amount

从交换收据获取需要支付的数量。

move
public fun swap_pay_amount(receipt: &FlashSwapReceipt): u64

参数:

  • receipt: &FlashSwapReceipt - 交换收据

返回: u64 - 需要支付的数量


add_liqudity_pay_amount

从添加流动性收据获取需要支付的数量。

move
public fun add_liqudity_pay_amount(
    receipt: &AddLiquidityReceipt
): (u64, u64)

参数:

  • receipt: &AddLiquidityReceipt - 添加流动性收据

返回: (u64, u64) - (代币A数量, 代币B数量)


pause

暂停池子。

move
public fun pause(
    account: &signer,
    pool_address: address
)

参数:

  • account: &signer - 协议权限签名者
  • pool_address: address - 池子地址

前置条件: 必须是协议权限账户


unpause

恢复池子。

move
public fun unpause(
    account: &signer,
    pool_address: address
)

参数:

  • account: &signer - 协议权限签名者
  • pool_address: address - 池子地址

前置条件: 必须是协议权限账户


update_fee_rate

更新池子费率。

move
public fun update_fee_rate(
    account: &signer,
    pool_address: address,
    fee_rate: u64
)

参数:

  • account: &signer - 协议权限签名者
  • pool_address: address - 池子地址
  • fee_rate: u64 - 新的费率

前置条件: 必须是协议权限账户,费率不能超过最大允许值

事件: 触发 UpdateFeeRateEvent


update_pool_uri

更新池子的位置NFT URI。

move
public fun update_pool_uri(
    account: &signer,
    pool_address: address,
    uri: String
)

参数:

  • account: &signer - 设置者账户签名者
  • pool_address: address - 池子地址
  • uri: String - NFT URI

前置条件: 必须有设置位置NFT URI的权限


initialize_rewarder

初始化奖励器。

move
public fun initialize_rewarder(
    account: &signer,
    pool_address: address,
    authority: address,
    index: u64,
    reward_token: Object<Metadata>
)

参数:

  • account: &signer - 协议权限签名者
  • pool_address: address - 池子地址
  • authority: address - 奖励器权限地址
  • index: u64 - 奖励器索引(0-2)
  • reward_token: Object<Metadata> - 奖励代币元数据

前置条件: 必须是协议权限账户


update_emission

更新奖励器发放速率。

move
public fun update_emission(
    account: &signer,
    pool_address: address,
    index: u8,
    emission_per_second: u128,
    reward_token: Object<Metadata>
)

参数:

  • account: &signer - 奖励器权限签名者
  • pool_address: address - 池子地址
  • index: u8 - 奖励器索引(0-2)
  • emission_per_second: u128 - 每秒发放数量
  • reward_token: Object<Metadata> - 奖励代币元数据

前置条件: 必须是奖励器权限账户

事件: 触发 UpdateEmissionEvent


transfer_rewarder_authority

转移奖励器权限。

move
public fun transfer_rewarder_authority(
    account: &signer,
    pool_address: address,
    index: u8,
    new_authority: address
)

参数:

  • account: &signer - 当前奖励器权限签名者
  • pool_address: address - 池子地址
  • index: u8 - 奖励器索引(0-2)
  • new_authority: address - 新权限地址

事件: 触发 TransferRewardAuthEvent


accept_rewarder_authority

接受奖励器权限。

move
public fun accept_rewarder_authority(
    account: &signer,
    pool_address: address,
    index: u8
)

参数:

  • account: &signer - 新奖励器权限签名者
  • pool_address: address - 池子地址
  • index: u8 - 奖励器索引(0-2)

事件: 触发 AcceptRewardAuthEvent


reset_init_price_v2

重置池子的初始价格(仅在池子无流动性时可用)。

move
public fun reset_init_price_v2(
    account: &signer,
    pool_address: address,
    new_initialize_price: u128
)

参数:

  • account: &signer - 设置者账户
  • pool_address: address - 池子地址
  • new_initialize_price: u128 - 新的初始价格平方根

前置条件:

  • 必须有重置初始价格的权限
  • 池子从未添加过流动性(position_index为1)

check_position_authority

检查位置权限(内部函数,用于验证位置所有权)。

move
public fun check_position_authority(
    account: &signer,
    pool_address: address,
    position_index: u64
)

参数:

  • account: &signer - 账户签名者
  • pool_address: address - 池子地址
  • position_index: u64 - 位置索引

前置条件: 账户必须持有对应的位置NFT


使用示例

TypeScript 示例

typescript
// 1. 查询池子信息
const poolInfo = await view('pool::get_pool_info', [poolAddress]);
console.log('Pool liquidity:', poolInfo.liquidity);
console.log('Current price:', poolInfo.current_fifrt_price);

// 2. 开启新位置
const positionIndex = await entry('pool::open_position', [
  account,
  poolAddress,
  tickLower,
  tickUpper
]);

// 3. 添加流动性
const receipt = await entry('pool::add_liquidity', [
  poolAddress,
  liquidity,
  positionIndex
]);
const [amountA, amountB] = await view('pool::add_liqudity_pay_amount', [receipt]);

// 4. 支付代币完成添加流动性
await entry('pool::repay_add_liquidity', [assetA, assetB, receipt]);

// 5. 查询用户位置
const userPositions = await view('pool::get_user_positions', [
  poolAddress,
  userAddress
]);

// 6. 计算交换结果
const swapResult = await view('pool::calculate_swap_result', [
  poolAddress,
  true,  // a2b
  true,  // by_amount_in
  1000   // amount
]);
console.log('Expected output:', swapResult.amount_out);
console.log('Fee amount:', swapResult.fee_amount);

// 7. 收集费用
const [feeA, feeB] = await entry('pool::collect_fee', [
  account,
  poolAddress,
  positionIndex,
  true  // update_reward
]);