Liquidity Management
V2 positions are identified by (token0, token1, fee, owner, tickLower, tickUpper). There is no positionId. Tokens may be symbols or class keys;
the SDK resolves and orders them.
Ticks and price ranges
addLiquidityByTicks is the precise API. Ticks must be aligned to the pool's
fee-tier spacing:
const tx = await gSwap.positions.addLiquidityByTicks({
token0: 'GALA',
token1: 'GUSDC',
fee: 3000,
tickLower: -6000,
tickUpper: 6000,
amount: '100',
amountIsToken0: true,
});
await tx.confirm();
The spacing is 0 → 200, 500 → 10, 3000 → 60, and 10000 → 200.
The lower tick must be below the upper tick, both ticks must be within the
contract bounds, and each must be divisible by the pool spacing.
Use addLiquidityByPrice when the UI works in token1-per-token0 prices. The
SDK converts the range to ticks and aligns it to the pool spacing. Prices are
branded (PriceIn, see Branded Types): a plain
string does not compile, so declare what it is with as PriceIn:
import type { PriceIn } from '@gala-chain/gswap-sdk';
const tx = await gSwap.positions.addLiquidityByPrice({
token0: 'GALA',
token1: 'GUSDC',
fee: 3000,
minPrice: '0.02' as PriceIn,
maxPrice: '0.04' as PriceIn,
amount: '100',
amountIsToken0: true,
});
Both add APIs require exactly one deposit side. Use
estimateAddLiquidity first to calculate the other side for the selected
range and current pool price.
Remove and collect
removeLiquidity accepts an optional withdrawal quantity. Supplying neither
quantity closes the position completely and sweeps its accrued fees:
const tx = await gSwap.positions.removeLiquidity({
token0: 'GALA',
token1: 'GUSDC',
fee: 3000,
tickLower: -6000,
tickUpper: 6000,
});
await tx.confirm();
When withdrawing partially, provide at most one of the SDK's amount0 or
amount1 options. The SDK maps it to the contract's
withdrawalQuantityToken0 or withdrawalQuantityToken1. The contract's
CollectPositionFees operation always sweeps the complete accrued fee balance;
there are no partial collect amount fields:
const tx = await gSwap.positions.collectPositionFees({
token0: 'GALA',
token1: 'GUSDC',
fee: 3000,
tickLower: -6000,
tickUpper: 6000,
});
await tx.confirm();
Creating a pool
CreatePool is the first place a token's trading symbol may be claimed. Both
symbols must be ASCII alphanumeric, globally available, and equal to the
token class's own symbol. A class key carries no symbol (collection and
symbol differ for many tokens, every launchpad token shares the collection
Token, and some collections contain $), so the SDK never derives one from
it. Tokens already in the trading-symbol registry resolve automatically; for a
token being registered for the first time you must pass token0Symbol /
token1Symbol (read from the token list or FetchTokenClasses), otherwise
createPool throws TOKEN_SYMBOL_NOT_REGISTERED. The canonical pair is ordered so the
lower symbol is token0 using plain string comparison. Supply exactly one
positive startingPrice or startingSqrtPrice:
const tx = await gSwap.positions.createPool({
token0: 'GALA|Unit|none|none',
token1: 'GUSDC|Unit|none|none',
fee: 3000,
startingPrice: '0.03',
});
console.log(tx.transactionId ?? tx.uniqueKey);
An optional name (omitted when undefined or empty) is sent as the DTO's
name.
CreatePool is not organization-gated. Treat symbols as a global namespace and
choose them carefully; the first successful pool can register them
permanently. CreatePool has no affected position to re-read, so its
confirm() result is null; use the executed result and transaction
metadata above. A duplicate pool is rejected by the gateway or chain.