1. 加载并获取池
import { Powfi, CpmmModule, PoolNotFoundError } from '@alephium/powfi-sdk'
import { ALPH_TOKEN_ID } from '@alephium/web3'
const powfi = Powfi.load({ networkId: 'mainnet', signer })
const tokenIn = ALPH_TOKEN_ID
const tokenOut = '<token id>'
let pool
try {
pool = await powfi.cpmm.getPoolState(tokenIn, tokenOut)
} catch (e) {
if (e instanceof PoolNotFoundError) throw new Error('No CPMM pool for this pair')
throw e
}
2. 报价(离线)
- 精确输入
- 精确输出
const quote = CpmmModule.computeSwapAmount({
state: pool,
tokenInId: tokenIn,
tokenOutId: tokenOut,
amountIn: 5n * 10n ** 18n, // sell exactly 5 ALPH
slippageBps: 50n
})
quote.tokenOutAmount // expected output
quote.minimalTokenOutAmount // guaranteed minimum
quote.priceImpact // percent
const quote = CpmmModule.computeSwapAmount({
state: pool,
tokenInId: tokenIn,
tokenOutId: tokenOut,
amountOut: 100n * 10n ** 6n, // buy exactly 100 units of a 6-decimal token
slippageBps: 50n
})
quote.tokenInAmount // expected input
quote.maximalTokenInAmount // worst-case input
import Decimal from 'decimal.js'
import { NumericUtils } from '@alephium/powfi-sdk'
const inHuman = NumericUtils.scaleDecimal(quote.tokenInAmount, quote.tokenInInfo.decimals)
const outHuman = NumericUtils.scaleDecimal(quote.tokenOutAmount, quote.tokenOutInfo.decimals)
const price = outHuman.div(inHuman) // tokenOut per tokenIn
3. 执行
const { address } = await signer.getSelectedAccount()
// Optional: pre-check balances to fail fast with a readable error
const bal = await powfi.nodeProvider.addresses.getAddressesAddressBalance(address)
const balances = new Map<string, bigint>([[ALPH_TOKEN_ID, BigInt(bal.balance)]])
for (const t of bal.tokenBalances ?? []) balances.set(t.id, BigInt(t.amount))
const result = await powfi.cpmm.swap(
{
tokenInId: tokenIn,
tokenOutId: tokenOut,
amountIn: 5n * 10n ** 18n,
slippageBps: 50n,
sender: address,
ttlMinutes: 10
},
balances
)
console.log(result.txId)
swap 在签名前会重新获取池状态并重新报价,所以它强制执行的最小值基于发送时的状态,而不是你展示给用户时的状态。
ALPH 余额检查只和兑换输入作比较。交易还需要几个
DUST_AMOUNT 的 ALPH 用于输出,外加 gas。当输入代币是 ALPH 时,请保留一些余量。4. 处理错误
| 错误 | 向用户展示 |
|---|---|
PriceImpactTooHighError | ”价格影响超过 5%,请减少数量。“ |
InsufficientBalanceError | 消息中已包含所需和可用数量。 |
InsufficientLiquidityError | 精确输出数量超过了池的储备量。 |
| 提到路由合约的节点错误 | 触发了滑点或截止时间,请重新报价。 |
把价格推到目标值
用于套利或再平衡时,swapTo 会计算把池价格推到目标价格所需的交易(目标价格为排序后顺序中每个 token0 值多少 token1,人类可读单位):
await powfi.cpmm.swapTo({ tokenA: tokenIn, tokenB: tokenOut, targetPrice: 0.052, sender: address, slippageBps: 30n })
swapTo 会跳过 5% 的价格影响保护。