Skip to main content
CPMM 池持有两种代币,按恒定乘积不变量 reserve0 × reserve1 = k 定价。每笔兑换向流动性提供者支付 0.3% 的手续费。流动性以同质化的 LP 代币表示,LP 代币的 ID 就是池 ID。

指南:在 CPMM 上兑换

指南:提供 CPMM 流动性

查询池

getPoolId(tokenA, tokenB)

离线推导代币对的合约 ID(会先对代币排序,所以顺序无关)。它同时也是 LP 代币 ID。

getPoolAddress(tokenA, tokenB)

返回代币对的合约地址(addressFromContractId(getPoolId(...)))。

poolExists(tokenA, tokenB)

getPoolState(tokenA, tokenB)

获取储备量和 LP 总量,并通过代币列表解析两个代币。代币对不存在时抛出 PoolNotFoundError。两个代币都必须在代币列表中。
object

getPoolProtocolFees(poolAddress)

代币对中已累计但尚未收取的协议费用。参数是池地址,而不是代币 ID。

报价(静态,离线)

所有报价函数都是静态纯函数。传入你已经获取的 CpmmPoolContractState。

CpmmModule.computeSwapAmount(params)

CpmmPoolContractState
必填
string
必填
string
必填
bigint
设置此项表示精确输入报价。
bigint
设置此项表示精确输出报价(仅在 amountIn 未定义时使用)。
bigint
必填
滑点容忍度,单位为基点。
object
精确输出时,如果 amountOut >= reserveOut,抛出 InsufficientLiquidityError。

CpmmModule.getAmountOut(state, tokenInId, amountIn) / getAmountIn(state, tokenOutId, amountOut)

带 0.3% 手续费的原始 x·y=k 公式:

CpmmModule.calcPriceImpact(reserve0, reserve1, tokenInId, token0Id, amountIn, amountOut)

返回以百分比表示的价格影响。

CpmmModule.computeLiquidityAmounts(params)

  • 已有池(设置了 poolState):给出一侧的数量(inputType: 'TokenA' 使用 amountA,'TokenB' 使用 amountB),函数会根据储备量推导另一侧的数量,以及你将获得的 LP 代币数量。
  • 新池(poolState 未定义):amountA 和 amountB 都必须提供。铸造的 LP = sqrt(amountA × amountB) − MINIMUM_LIQUIDITY(1000 个单位被永久锁定)。如果 sqrt(amountA × amountB) <= 1000,抛出 InsufficientLiquidityError。
返回 { tokenAId, tokenBId, amountA, amountB, shareAmount, sharePercentage, state? },其中 sharePercentage 是存入后你在池中的份额百分比。

CpmmModule.computeRemoveLiquidityAmounts(state, totalLiquidity, liquidityToRemove)

销毁 liquidityToRemove 个 LP 代币后返还的代币数量,以及你剩余的份额。totalLiquidity 是你的 LP 余额。如果 liquidityToRemove > totalLiquidity 则抛出错误。

CpmmModule.computeClaimableAmounts(state, liquidityBalance)

LP 余额对应的全部底层价值:{ token0, amount0, token1, amount1, ... }。

CpmmModule.minimalAmount(amount, slippage) / maximalAmount(amount, slippage)

滑点辅助函数。见数量与滑点。

兑换

swap(params, balances?)

获取最新池状态、报价、检查价格影响,然后通过路由合约执行 SwapMinOut(精确输入)或 SwapMaxIn(精确输出)。需要签名器。
string
必填
string
必填
bigint
精确输入数量。
bigint
精确输出数量(在 amountIn 未定义时使用)。
bigint
必填
基点。
string
必填
付款并接收的地址,通常是签名器的地址。
number
默认值:"60"
截止时间。
bigint
可选的集成方手续费,以输入代币计。
string
必须与 fee 一起提供。
Map<tokenId, bigint>
可选的预检查:如果提供了此参数且 balances.get(tokenIn) < 输入 + 手续费,会在签名前抛出 InsufficientBalanceError。对于 ALPH,请用 ALPH_TOKEN_ID 作为键。
如果 priceImpact >= 5,抛出 PriceImpactTooHighError。

simSwap(params)

获取池状态并返回 swap 会使用的报价,不发送任何交易。如果 slippageBps 为空,默认 100n。

swapTo(params)

计算能把池价格推到 targetPrice 的精确输入交易并执行,方向自动推断。**跳过价格影响检查。**如果目标价格等于当前价格则抛出错误。适用于套利,以及把测试池的价格拉回锚定值。

流动性

addLiquidity(params, balances?)

CpmmPoolContractState
必填
来自 getPoolState 的最新状态。
string
必填
必须都是池中的代币(顺序任意)。
bigint
必填
期望数量,都必须大于 0。用 computeLiquidityAmounts 得到一对平衡的数量。
bigint
必填
作为最小值应用到两个数量上。池为空时忽略。
string
必填
number
默认值:"60"
路由合约按最优比例存入,并向 sender 铸造 LP 代币。

removeLiquidity(params)

CpmmPoolContractState
必填
bigint
必填
要销毁的 LP 代币数量。
bigint
你的 LP 余额(用于计算份额)。默认为 poolState.totalSupply。
bigint
必填
作为最小值应用到两个输出数量上。
string
必填
number
默认值:"60"

computeClaimableAmounts(tokenAId, tokenBId, liquidityBalance)

实例方法版本:获取池状态,然后返回 LP 余额对应的 { token0, amount0, token1, amount1 }。

创建池

createPool(params)

string
必填
string
必填
支付 1 ALPH 的合约押金。
{ tokenAAmount: bigint; tokenBAmount: bigint }
如果设置,会在一笔交易中创建代币对并存入初始流动性(CreatePairAndAddLiquidity),两者的比例决定初始价格。如果省略,只创建代币对(CreatePair,会附加每种代币各 1 个最小单位)。

配置

getConfig() 返回当前生效的 CpmmConfig(groupIndex、factoryId、routerId)。setConfig(config) 覆盖它。getCpmmConfig() 重新读取打包的部署文件。

常量