Skip to main content
1

Load the pool and fee tier

2

Choose a range

Convert human prices (token1 per token0) to ticks aligned to the tier’s spacing:
For a full-range position, use TickUtils.getMinPriceFromTick and getMaxPriceFromTick, which return spacing-aligned extreme ticks.
3

Size the deposit

Given the amount of one token, compute the matching amount of the other at the current price:
If the current price is outside the range, the position is single-sided: only token0 (price at or below tickLower) or only token1 (price above the range) is needed.
4

Add liquidity

Keep the returned positionId: the next steps use it to read, collect from, and withdraw the position. To top up the same range later, pass existingPosition: true, which attaches the position token.
5

Monitor fees and value

tokensOwed holds fees that are already credited to the position (token0, token1, reward). The pool’s positionInfo view (powfi.clmm.positionInfo) also returns current token amounts and fees. See the CLMM reference.To value the position, pass -liquidity to ClmmLiquidityUtils.getAmountsForLiquidity with the current sqrtPriceX96 and the range bounds.
6

Collect fees

7

Withdraw

removeLiquidity also collects in the same transaction: the withdrawn tokens and any accrued fees and rewards go to your address, so no separate collectTokens call is needed.

Creating a new pool

Anyone can create a CLMM pool. There is no allowlist of creators or tokens on-chain. Before you create one, note:
  • Only existing fee tiers can be used. Pools are created under a fee tier (configIndex) that the Powfi team has already set up. You can’t choose your own fee or tick spacing. List the available tiers with getAllPoolConfigs().
  • One pool per token pair and fee tier. The pool address is derived from the pair and the tier, so creation fails if that pool already exists.
  • The creator sets the initial price. The tick you pass becomes the pool’s starting price, and your first position is minted at that price. If it’s far from the market price, arbitrageurs will trade against your position right away.
  • Both tokens should be in the token list. The contract accepts any token, but the SDK’s getPoolState and related methods throw for tokens that aren’t in the token list.
If poolExists(token0, token1, configIndex) is false, create the pool and seed the first position in one call:
To compute a position ID yourself (for example, to check whether a wallet already holds a range before adding), don’t pass a groupless address as-is: it gives the wrong ID. Normalize it first with normalizeAddress(address, powfi.clmm.getClmmConfig().groupIndex), or use PoolUtils.getPositionId(poolAddress, owner, ...), which normalizes for you.