Skip to main content
CLMM 池采用 Uniswap V3 风格:流动性提供者选择一个价格区间(tickLower–tickUpper),只有当价格处于区间内时才赚取手续费。每个池由代币对加费率档位(configIndex)确定。价格存储为 sqrtPriceX96 = sqrt(token1/token0) × 2^96。

指南:在 CLMM 上兑换

指南:开设和管理头寸

费率档位(池配置)

费率档位是在工厂合约中注册的 PoolConfig 合约,索引从 0n 开始。每个池恰好引用一个档位。

查询池

getPoolState(poolId)

object
池不存在时抛出 PoolNotFoundError。

其他池查询

兑换

simulateSwap(params)

在节点上运行池的 simulateSwap 视图方法(不发交易),返回兑换经过的流动性曲线。把结果传给 PoolUtils.offlineSwap 即可在本地计算输出数量。
bigint
必填
string
必填
池中的两个代币(顺序任意,用于定位池)。
boolean
必填
true 表示卖出排序后的 token0 换取 token1(价格下降)。
bigint
必填
正数 = 精确输入,负数 = 精确输出。
string
来自 buildSwapPath 的多跳路径(可选)。
string[]
多跳路径涉及的其他池的地址。
object

swap(params)

通过 SwapWithoutAccount 脚本(设置了集成方手续费时使用 SwapWithoutAccountWithFee)执行单池兑换。签名器既是付款方也是接收方。
string
必填
输入代币(不一定是池排序后的 token0)。
string
必填
输出代币。
bigint
必填
指定数量:正数 = 精确输入,负数 = 精确输出(期望输出取负)。
bigint
必填
要附加的输入代币数量。精确输入时与 amount 相同;精确输出时为你愿意支付的最大输入(先模拟,再加上滑点)。
bigint
必填
基点,会被转换为 sqrtPriceLimitX96。
bigint[]
必填
要经过的费率档位。目前只使用 routePlan[0]。
bigint / string
可选的集成方手续费,以输入代币计。
swap() 总是发送空的多跳路径,所以只在单个池中兑换。如需多跳,请用 buildSwapPath 构建路径,并直接调用 ClmmScripts 中的 SwapWithoutAccount 脚本。

swapTo(params)

持续兑换直到池价格达到 targetSqrtPriceX96,最多花费 amountInMax 的 tokenIn。如果目标价格在当前价格的错误一侧,链上会失败(错误码 106,InvalidSqrtPriceLimit)。

buildSwapPath(tokenId, configIndex)

为 simulateSwap({ data }) 编码额外的一跳:tokenId + configIndex(4 个十六进制字符)。

流动性头寸

头寸由 池 + 所有者 + tickLower + tickUpper 确定。头寸合约 ID 同时也是头寸代币 ID:所有者持有 1 个单位,修改头寸时需要附加它。

getPositionId(poolId, owner, tickLower, tickUpper)

离线推导头寸 ID。对于无分组地址,请传入规范化后的 owner(见分组与地址)。PoolUtils.getPositionId(poolAddress, owner, ...) 会自动规范化。

createPool(...)

以 tick 对应的价格创建池,并在 [tickLower, tickUpper] 内铸造第一个头寸。代币及其数量、tick 都会在内部排序。会为新合约附加 6 × MINIMAL_CONTRACT_DEPOSIT 的 ALPH。

addLiquidity(params)

string
必填
池中的代币。请排序后传入(sortTokens),并让 amount0 / amount1 与该顺序对应。
bigint
必填
bigint
必填
必须是该档位 tickSpacing 的整数倍。用 TickUtils.getAlignedTick 对齐。
bigint
必填
期望数量。合约会在不超过这些数量的前提下存入最大的平衡数量。
bigint
必填
作用于价格的基点。最小数量由价格边界推导。
string
头寸所有者,默认为签名器。
boolean
向你已持有的头寸追加流动性时设为 true(会附加头寸代币)。签名者必须持有该头寸的 NFT,SDK 会自动附上。
头寸的押金(dustAmount)通过 PositionManager.getSqrtPricesX96 从链上读取。 两步版本: getAddLiquidityParams(p) 返回 [positionId, positionManager, params] 而不发送,addLiquidityFromParams(positionId, positionManager, params) 再执行。可以用它展示带有精确最小数量的确认界面。

removeLiquidity(params)

减少头寸的流动性,并在同一笔交易中收取全部累计的手续费和奖励。代币发送给签名器。
必填
确定池。
必填
确定头寸。
bigint
必填
要移除的流动性单位(先读取头寸当前的 liquidity,再取一部分)。
'token0' | 'token1'
必填
baseAmount 指的是哪一侧。
bigint
必填
至少要收到的 base 代币数量。
bigint
必填
至少要收到的另一种代币数量。虽然名字里有 Max,但它在链上是作为最小值传递的。
两个最小值都传 0n 即可关闭检查。

collectTokens(params)

把累计的手续费和奖励收取到 recipient。它不会移除流动性;如需移除,请使用 removeLiquidity。
必填
确定头寸。
string
必填
bigint
必填
收取上限。要全部收取,请使用 U128_MAX 量级的值(例如 UNLIMITED_AMOUNT)。

positionInfo(params)

调用池的 positionInfo 视图方法,原样返回结果。fees 包含三项:token0、token1 和池的奖励代币。SDK 会把累加器参数(acc、iacc0、iacc1、t0、acct0)直接传给合约,其含义请参考 Pool 合约源码。 要读取头寸的原始流动性,请获取头寸合约的状态:

流动性挖矿奖励

每个池最多可以运行三个奖励计划(MAX_REWARDS = 3),以 token0、token1 或池的额外奖励代币(token2)发放。奖励计划由 Powfi 团队设置和注资。
  • getPoolRewardState(poolId) 返回奖励代币,以及每个计划的 amount、openTime 和 endTime(毫秒时间戳)。
  • 头寸累计的奖励体现在 positionInfo(...).fees 中:token0 奖励在 fees[0],token1 奖励在 fees[1],其他代币的奖励在 fees[2]。通过 collectTokens 领取。

推荐(DEX)账户

Powfi 通过 DexAccountRoot 下每个用户的 DexAccount 合约跟踪推荐关系。

配置

用 getClmmConfig() 读取当前生效的配置,用 setConfig() 覆盖。getConfig() 会重新读取打包的部署文件。

常量