> For the complete documentation index, see [llms.txt](https://docs.ferra.ag/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ferra.ag/integration/clmm/typescript-sdk/close-position.md).

# Close Position

### Quick Start

```typescript
const tx = await sdk.Position.closePositionTransactionPayload({
  pool_id: '0x...',
  pos_id: '0x...',
  coinTypeA: '0x2::sui::SUI',
  coinTypeB: '0x...::usdc::USDC',
  min_amount_a: '490000000',
  min_amount_b: '490000'
  collect_fee: true
  rewarder_coin_types: [],
})
```

### Parameters

| Parameter             | Type      | Description                                           |
| --------------------- | --------- | ----------------------------------------------------- |
| `pool_id`             | string    | The object id about which pool you want to operation. |
| `pos_id`              | string    | Position object ID                                    |
| `coinTypeA`           | string    | First token type                                      |
| `coinTypeB`           | string    | Second token type                                     |
| `min_amount_a`        | string    | Minimum token A to receive                            |
| `min_amount_b`        | string    | Minimum token B to receive                            |
| `collect_fee`         | boolean   | Indicates whether to collect fees during the removal. |
| `rewarder_coin_types` | string\[] | Coin types associated with rewarder contracts.        |

### Close with Slippage Protection

```typescript
async function estimateClosePosition(
  pool,
  position,
  amountABigint,
  amountBBigint
) {
  const slippage = new Percentage(new BN(5), new BN(1000));
  const { curSqrtPrice, lowerSqrtPrice, upperSqrtPrice } = getCoinsRate(
    pool,
    position
  );

  const tokenAmounts = adjustForCoinSlippage(
    {
      coinA: new BN(amountABigint.toFixed(0)),
      coinB: new BN(amountBBigint.toFixed(0)),
    },
    slippage,
    false
  );
  const liquidity = ClmmPoolUtil.estimateLiquidityFromcoinAmounts(
    curSqrtPrice,
    Number(position.tick_lower_index),
    Number(position.tick_upper_index),
    {
      coinA: new BN(Math.ceil(amountABigint)),
      coinB: new BN(Math.ceil(amountBBigint)),
    }
  );
  return {
    tokenMaxA: tokenAmounts.tokenMaxA,
    tokenMaxB: tokenAmounts.tokenMaxB,
    lowerTick: lowerSqrtPrice,
    upperTick: upperSqrtPrice,
    curSqrtPrice,
    liquidity,
  };
}

function getCoinsRate(pool, position) {
  const curSqrtPrice = new BN(pool.current_sqrt_price);

  const lowerSqrtPrice = TickMath.tickIndexToSqrtPriceX64(
    position.tick_lower_index
  );

  const upperSqrtPrice = TickMath.tickIndexToSqrtPriceX64(
    position.tick_upper_index
  );

  const amounts = ClmmPoolUtil.getCoinAmountFromLiquidity(
    new BN(position.liquidity),
    curSqrtPrice,
    lowerSqrtPrice,
    upperSqrtPrice,
    false
  );

  const coinAValue = fromDecimalsAmount(
    amounts.coinA.toNumber(),
    pool.coinA?.decimals ?? 1
  );

  const coinBValue = fromDecimalsAmount(
    amounts.coinB.toNumber(),
    pool.coinB?.decimals ?? 1
  );

  const total = coinAValue + coinBValue;
  const percent = {
    ratioA: coinAValue / total,
    ratioB: coinBValue / total,
  };

  return {
    percent,
    curSqrtPrice,
    lowerSqrtPrice,
    upperSqrtPrice,
  };
}

```

### Complete Example

<pre class="language-typescript"><code class="lang-typescript">const position = await sdk.Position.getPositionById(positionId)
const pool = await sdk.Pool.getPool(position.pool)
const amountA = 100000000
const amountB = 2000000000
const percent = 0.2 
const { tokenMaxA, tokenMaxB, liquidity } = await estimateRemovePosition(poolOnchain, position, amountA, amountB);
const rewards = await ferraSDK.Rewarder.fetchPositionRewarders(
        poolOnchain,
        position.pos_object_id
      );
const rewardCoinTypes = rewards
        .filter((item) => Number(item.amount_owed) > 0)
        .map((item) => item.coin_address);
const closeLiquidityPayloadParams: ClosePositionParams = {
        coinTypeA: poolOnchain.coinTypeA,
        coinTypeB: poolOnchain.coinTypeB,
        pool_id: poolOnchain.poolAddress,
        min_amount_a: tokenMaxA.toString(),
        min_amount_b: tokenMaxB.toString(),
        collect_fee: true,
        rewarder_coin_types: rewardCoinTypes,
        pos_id: position.pos_object_id,
      };
<strong>const tx = await sdk.Position.closePositionTransactionPayload(closeLiquidityPayloadParams);       
</strong>const result = await sdk.fullClient.signAndExecuteTransaction({
  transaction: tx,
  signer: keypair
})
</code></pre>

### Close vs Remove Liquidity

| Action           | Effect                    | Position NFT    |
| ---------------- | ------------------------- | --------------- |
| Remove Liquidity | Withdraws tokens          | Remains (empty) |
| Close Position   | Withdraws all + burns NFT | Destroyed       |

### Error Handling

```typescript
try {
  const tx = await sdk.Position.closePositionTransactionPayload(params)
} catch (error) {
  if (error.message.includes('Slippage exceeded')) {
    console.log('Price moved, increase slippage')
  }
  if (error.message.includes('Position not found')) {
    console.log('Position does not exist')
  }
}
```

### Important Notes

* Closing automatically collects all fees and rewards
* Position NFT is burned and cannot be recovered
* All liquidity must be removed (SDK handles this)
* Cannot close position with active orders
*
