# Position Management

## Get user positions

<pre class="language-typescript"><code class="lang-typescript"><strong>const positions: ClmmPosition[] = positionManager.getUserPositions('0xaddress');
</strong></code></pre>

## Get position reward

```typescript
const positions: ClmmPosition[] = positionManager.getUserPositions('0xaddress');
const positionWithReward: ClmmPosition[] = positionManager.getPositionReward(positions);
```

## Open/Increase a Position

```typescript
import { ClmmPosition, CoinAmount, Percent, BN } from '@flowx-finance/sdk';
import { TransactionResult } from '@mysten/sui/transactions';


// Method 1: Create position with specific liquidity amount
const tickLower = -3000; // Lower price tick (must be divisible by tick spacing: 60 for MEDIUM fee)
const tickUpper = 3000; // Upper price tick (must be divisible by tick spacing: 60 for MEDIUM fee)
const liquidity = new BN(1000);

const position = new ClmmPosition({
  objectId: '0x...', // Optional: Your position object id if you want increase exist position
  owner: '0x...', // Your address
  pool: pool,
  tickLower,
  tickUpper,
  liquidity,
  coinsOwedX: 0,
  coinsOwedY: 0,
  feeGrowthInsideXLast: 0,
  feeGrowthInsideYLast: 0,
  rewardInfos: [],
});

// Method 2: Create position with specific token amounts
const amountX = new BN('1000000000'); // 1 SUI (9 decimals)
const amountY = new BN('1000000'); // 1 USDC (6 decimals)

const positionFromAmounts = ClmmPosition.fromAmounts({
  objectId: '0x...', // Optional: Your position object id if you want increase exist position
  owner: '0x...', // Your address
  pool: pool,
  tickLower: -3000,
  tickUpper: 3000,
  amountX: amountX,
  amountY: amountY,
  useFullPrecision: true, // Use full precision for liquidity calculation
});

// Method 3: Create position with only amountX (single-sided liquidity)
const positionOnlyX = ClmmPosition.fromAmountX({
  objectId: '0x...', // Optional: Your position object id if you want increase exist position
  owner: '0x...', // Your address
  pool: pool,
  tickLower: -3000,
  tickUpper: 3000,
  amountX: amountX, // Only provide amountX
  // amountY not provided - will be calculated based on current price
  useFullPrecision: true,
});

// Method 4: Create position with only amountY (single-sided liquidity)
const positionOnlyY = ClmmPosition.fromAmountY({
  objectId: '0x...', // Optional: Your position object id if you want increase exist position
  owner: '0x...', // Your address
  pool: pool,
  tickLower: -3000,
  tickUpper: 3000,
  amountY: amountY, // Only provide amountY
  // amountX not provided - will be calculated based on current price
  useFullPrecision: true,
});

// Create position with liquidity

const options = {
  slippageTolerance: new Percent(1, 100), // 1% slippage
  deadline: Date.now() + 3600 * 1000, // 1 hour from now
  createPosition: true,
};
const tx = new Transaction();
const createdPosition = positionManager.tx(tx).increaseLiquidity(position, options);
tx.transferObjects([createdPosition], recipient);
```

## Decrease Liquidity

<pre class="language-typescript"><code class="lang-typescript">
// Define MaxU64 constant for convenience
const MaxU64 = new BN('18446744073709551615');

<strong>// Example 1: Remove 50% of liquidity
</strong>const positionId = '0x...'; // Position object ID
const position = await positionManager.getPosition(positionId);
const liquidityToRemove = position.liquidity.div(new BN(2));

const positionWillBeDecreased = new ClmmPosition({
  owner: position.owner,
  pool: position.pool,
  tickLower: position.tickLower,
  tickUpper: position.tickUpper,
  liquidity: liquidityToRemove,
  coinsOwedX: 0,
  coinsOwedY: 0,
  feeGrowthInsideXLast: 0,
  feeGrowthInsideYLast: 0,
  rewardInfos: [],
});

const burnAmounts = {
  amountX: positionWillBeDecreased.amountX,
  amountY: positionWillBeDecreased.amountY,
};

const decreaseOptions = {
  slippageTolerance: new Percent(1, 100),
  deadline: Date.now() + 3600 * 1000, // 1 hour from now
  collectOptions: {
    expectedCoinOwedX: CoinAmount.fromRawAmount(coinX, burnAmounts.amountX),
    expectedCoinOwedY: CoinAmount.fromRawAmount(coinY, burnAmounts.amountY),
  },
};

const tx = new Transaction();
positionManager.tx(tx).decreaseLiquidity(position, decreaseOptions);

// Example 2: Remove all liquidity and close position
const positionToClose = await positionManager.getPosition(positionId);

const closeOptions = {
  slippageTolerance: new Percent(1, 100),
  deadline: Date.now() + 3600 * 1000, // 1 hour from now
  collectOptions: {
    // Use MaxU64 to ensure we collect all available fees regardless of fee growth during processing
    expectedCoinOwedX: CoinAmount.fromRawAmount(coinX, MaxU64),
    expectedCoinOwedY: CoinAmount.fromRawAmount(coinY, MaxU64),
  },
};

const closeTx = new Transaction();
positionManager.tx(closeTx).decreaseLiquidity(positionToClose, closeOptions);

// Get all available rewards before closing
const rewards = await positionToClose.getRewards();

// Collect all available rewards
for (let i = 0; i &#x3C; rewards.length; i++) {
  if (rewards[i].gt(new BN(0))) {
    const collectRewardOptions = {
      expectedRewardOwed: CoinAmount.fromRawAmount(
        positionToClose.pool.poolRewards[i].coin,
        MaxU64 // Use MaxU64 for rewards as well
      ),
      recipient: '0x...', // Optional recipient
    };

    positionManager.collectPoolReward(positionToClose, i, collectRewardOptions);
  }
}

// Close the position (burn the NFT)
positionManager.closePosition(positionToClose, closeTx);
</code></pre>

## Collecting Fees and Rewards

```typescript

// Define MaxU64 constant for convenience
const MaxU64 = new BN('18446744073709551615');

// Example 1: Collect accumulated fees only
const positionId = '0x...'; // Position object ID
const position = await positionManager.getPosition(positionId);

// Get current fees
const fees = await position.getFees();

if (fees.amountX.gt(new BN(0)) || fees.amountY.gt(new BN(0))) {
  const collectFeeOptions = {
    expectedCoinOwedX: CoinAmount.fromRawAmount(coinX, MaxU64),
    expectedCoinOwedY: CoinAmount.fromRawAmount(coinY, MaxU64),
    recipient: '0x...', // Optional recipient
  };

  const tx = new Transaction();
  positionManager.tx(tx);

  // Collect returns the collected coin objects
  const [collectedX, collectedY] = positionManager.collect(position, collectFeeOptions) as TransactionResult;

  // Transfer to recipient if not specified in collectFeeOptions
  if (!collectFeeOptions.recipient) {
    tx.transferObjects([collectedX, collectedY], position.owner);
  }
}

// Example 2: Collect specific reward tokens
const rewards = await position.getRewards();

for (let i = 0; i < rewards.length; i++) {
  if (rewards[i].gt(new BN(0))) {
    const collectRewardOptions = {
      expectedRewardOwed: CoinAmount.fromRawAmount(position.pool.poolRewards[i].coin, MaxU64),
      recipient: '0x...', // Optional recipient
    };

    const tx = new Transaction();
    positionManager.tx(tx);
    positionManager.collectPoolReward(position, i, collectRewardOptions);
  }
}
```

## Rebalance example

```typescript
const tx = new Transaction();
const rebalancer = new Rebalancer({
  network: "mainnet",
});
const newPosition = await rebalancer.rebalance(
  clmmPosition,
  tickLower,
  tickUpper,
  {
    slippageTolerance: 1000,
    priceImpactPercentThreshold: -5000,
    minZapAmounts: {
      amountX: 1000,
      amountY: 1000,
    },
  },
)(tx);
tx.transferObjects([newPosition], position.owner);

```


---

# 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.flowx.finance/developer/flowx-sdk/clmm-management/position-management.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.
