# 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
*


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.ferra.ag/integration/clmm/typescript-sdk/close-position.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
