> For the complete documentation index, see [llms.txt](https://cetus-1.gitbook.io/cetus-developer-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cetus-1.gitbook.io/cetus-developer-docs/developer/via-sdk-v2/sdk-modules/cetusprotocol-dlmm-sdk/add-liquidity.md).

# Add Liquidity

## 1. Add Liquidity

The DLMM SDK provides two main methods for adding liquidity:

1. **`calculateAddLiquidityInfo(option)`** - Calculates the liquidity distribution across bins
2. **`addLiquidityPayload(option, tx?)`** - Creates the transaction payload for adding liquidity

### **Method 1: `calculateAddLiquidityInfo`**

This method calculates how liquidity should be distributed across different bins based on your strategy and parameters.

**Parameters for `CalculateAddLiquidityOption`:**

```
interface CalculateAddLiquidityOption {
  pool_id: string                    // Pool ID
  amount_a: string                   // Amount of token A to add
  amount_b: string                   // Amount of token B to add
  active_id: number                  // Current active bin ID
  bin_step: number                   // Bin step size
  lower_bin_id: number               // Lower bound of bin range
  upper_bin_id: number               // Upper bound of bin range
  active_bin_of_pool?: {             // Active bin amounts (if active bin is in range)
    amount_a: string
    amount_b: string
  }
  strategy_type: StrategyType        // Liquidity strategy (Spot, BidAsk, Curve)
}
```

**Parameters for `CalculateAddLiquidityAutoFillOption`:**

```
interface CalculateAddLiquidityAutoFillOption {
  pool_id: string                    // Pool ID
  coin_amount: string                // Fixed amount of one token
  fix_amount_a: boolean              // true for token A, false for token B
  active_id: number                  // Current active bin ID
  bin_step: number                   // Bin step size
  lower_bin_id: number               // Lower bound of bin range
  upper_bin_id: number               // Upper bound of bin range
  active_bin_of_pool?: {             // Active bin amounts (if active bin is in range)
    amount_a: string
    amount_b: string
  }
  strategy_type: StrategyType        // Liquidity strategy (Spot, BidAsk, Curve)
}
```

### **Method 2: `addLiquidityPayload`**

This method creates the transaction payload for adding liquidity to an existing position or opening a new position.

**Parameters for `AddLiquidityOption` (existing position):**

```
interface AddLiquidityOption {
  pool_id: string                    // Pool ID
  bin_infos: BinLiquidityInfo        // Calculated bin distribution from calculateAddLiquidityInfo
  coin_type_a: string                // Token A coin type
  coin_type_b: string                // Token B coin type
  active_id: number                  // Current active bin ID
  position_id: string                // Existing position ID
  collect_fee: boolean               // Whether to collect fees
  reward_coins: string[]             // Reward coin types
  strategy_type: StrategyType        // Liquidity strategy
  use_bin_infos: boolean             // Whether to use calculated bin_infos
  max_price_slippage: number         // Maximum price slippage tolerance
  bin_step: number                   // Bin step size
}
```

**Parameters for `OpenAndAddLiquidityOption` (new position):**

```
interface OpenAndAddLiquidityOption {
  pool_id: string                    // Pool ID
  bin_infos: BinLiquidityInfo        // Calculated bin distribution from calculateAddLiquidityInfo
  coin_type_a: string                // Token A coin type
  coin_type_b: string                // Token B coin type
  lower_bin_id: number               // Lower bound of bin range
  upper_bin_id: number               // Upper bound of bin range
  active_id: number                  // Current active bin ID
  strategy_type: StrategyType        // Liquidity strategy
  use_bin_infos: boolean             // Whether to use calculated bin_infos
  max_price_slippage: number         // Maximum price slippage tolerance
  bin_step: number                   // Bin step size
}
```

**Complete Example - Adding Liquidity to Existing Position:**

```
// Step 1: Calculate liquidity distribution
const calculateOption: CalculateAddLiquidityOption = {
  pool_id: '0x...',
  amount_a: '1000000',
  amount_b: '1200000',
  active_id: 100,
  bin_step: 2,
  lower_bin_id: 90,
  upper_bin_id: 110,
  active_bin_of_pool: amounts_in_active_bin, // Optional: if active bin is in range
  strategy_type: StrategyType.Spot
}

const bin_infos = await sdk.Position.calculateAddLiquidityInfo(calculateOption)

// Step 2: Create transaction payload
const addLiquidityOption: AddLiquidityOption = {
  pool_id: '0x...',
  bin_infos: bin_infos,
  coin_type_a: '0x...::usdc::USDC',
  coin_type_b: '0x...::usdt::USDT',
  active_id: 100,
  position_id: '0x...',
  collect_fee: true,
  reward_coins: [],
  strategy_type: StrategyType.Spot,
  use_bin_infos: false,
  max_price_slippage: 0.01,
  bin_step: 2
}

const tx = sdk.Position.addLiquidityPayload(addLiquidityOption)
```

**Complete Example - Opening New Position:**

```
// Step 1: Calculate liquidity distribution
const calculateOption: CalculateAddLiquidityOption = {
  pool_id: '0x...',
  amount_a: '1000000',
  amount_b: '1200000',
  active_id: 100,
  bin_step: 2,
  lower_bin_id: 90,
  upper_bin_id: 110,
  active_bin_of_pool: amounts_in_active_bin,
  strategy_type: StrategyType.Spot
}

const bin_infos = await sdk.Position.calculateAddLiquidityInfo(calculateOption)

// Step 2: Create transaction payload for new position
const openPositionOption: OpenAndAddLiquidityOption = {
  pool_id: '0x...',
  bin_infos: bin_infos,
  coin_type_a: '0x...::usdc::USDC',
  coin_type_b: '0x...::usdt::USDT',
  lower_bin_id: 90,
  upper_bin_id: 110,
  active_id: 100,
  strategy_type: StrategyType.Spot,
  use_bin_infos: false,
  max_price_slippage: 0.01,
  bin_step: 2
}

const tx = sdk.Position.addLiquidityPayload(openPositionOption)
```

## 2. **Important Parameter Notes:**

* **`active_bin_of_pool`**: This parameter is crucial when the active bin falls within your position's range. Use `getActiveBinIfInRange()` to get the correct values.
* **`use_bin_infos`**: When `false`, the contract calculates liquidity distribution internally; when `true`, it uses the provided `bin_infos`.
* **`max_price_slippage`**: Protects against price movements during transaction execution (e.g., 0.01 = 1% slippage tolerance).
* **`collect_fee`**: Only applicable for existing positions; determines whether to collect accumulated fees when adding liquidity.
* **`strategy_type`**: Affects how liquidity is distributed across bins:
  * `Spot`: Even distribution around current price.
  * `BidAsk`: Concentrated at specific price levels.
  * `Curve`: Smooth distribution following a curve.

There are three strategies for adding liquidity: Spot, BidAsk, and Curve. Here's how to use each:

### **1. Spot Strategy**

```typescript
// Get pool information
const pool = await sdk.Pool.getPool(pool_id)
const { active_id, bin_step, bin_manager } = pool

// Get amounts in active bin if it's within the range
const amounts_in_active_bin = await sdk.Position.getActiveBinIfInRange(
  bin_manager.bin_manager_handle,
  lower_bin_id,
  upper_bin_id,
  active_id,
  bin_step
)

// Calculate liquidity distribution
const calculateOption = {
  pool_id,
  amount_a: '1000000',
  amount_b: '1200000',
  active_id,
  bin_step,
  lower_bin_id: -10,
  upper_bin_id: 10,
  amount_a_in_active_bin: amounts_in_active_bin?.amount_a || '0',
  amount_b_in_active_bin: amounts_in_active_bin?.amount_b || '0',
  strategy_type: StrategyType.Spot
}
const bin_infos = await sdk.Position.calculateAddLiquidityInfo(calculateOption)

// For new position
const addOption = {
  pool_id,
  amount_a,
  amount_b,
  active_id,
  bin_step,
  lower_bin_id,
  upper_bin_id,
  active_bin_of_pool: amounts_in_active_bin,
  strategy_type: StrategyType.Spot,
}
const tx = sdk.Position.addLiquidityPayload(addOption)

// For existing position
const addOption = {
  pool_id,
  bin_infos: bin_infos,
  coin_type_a,
  coin_type_b,
  active_id,
  position_id,
  collect_fee: true,
  reward_coins: [],
  strategy_type: StrategyType.Spot,
  use_bin_infos: false,
  max_price_slippage: 0.01,
  bin_step,
}
const tx = sdk.Position.addLiquidityPayload(addOption)
```

Note: The `amount_a_in_active_bin` and `amount_b_in_active_bin` parameters are used to calculate the correct liquidity distribution when the active bin is within your position's range. These values are obtained using the `getActiveBinIfInRange` method, which:

1. Checks if the active bin is within your specified range
2. Returns the amounts of both tokens in the active bin if it is within range
3. Returns undefined if the active bin is outside the range

### **2. BidAsk Strategy**

```typescript
// Similar to Spot strategy but with different strategy_type
const calculateOption = {
  amount_a: '1000000',
  amount_b: '1200000',
  active_id,
  bin_step,
  lower_bin_id: -10,
  upper_bin_id: 10,
  amount_a_in_active_bin: '0',
  amount_b_in_active_bin: '0',
  strategy_type: StrategyType.BidAsk
}
```

## **3. Curve Strategy**

```typescript
// Similar to Spot strategy but with different strategy_type
const calculateOption = {
  amount_a: '1000000',
  amount_b: '1200000',
  active_id,
  bin_step,
  lower_bin_id: -10,
  upper_bin_id: 10,
  amount_a_in_active_bin: '0',
  amount_b_in_active_bin: '0',
  strategy_type: StrategyType.Curve
}
```

## **3. Add Liquidity with Fixed Amount**

```typescript
// Calculate with fixed amount of one token
const calculateOption = {
  coin_amount: '1000000',
  fix_amount_a: true, // true for token A, false for token B
  active_id,
  bin_step,
  lower_bin_id: -10,
  upper_bin_id: 10,
  amount_a_in_active_bin: '0',
  amount_b_in_active_bin: '0',
  strategy_type: StrategyType.Spot // or BidAsk or Curve
}
```

## **4. Add Liquidity with Price**

```typescript
// Add liquidity with specific price range
const addOption = {
  pool_id,
  bin_infos,
  coin_type_a: pool.coin_type_a,
  coin_type_b: pool.coin_type_b,
  price_base_coin: 'coin_a',
  price: price.toString(),
  lower_price,
  upper_price,
  bin_step,
  amount_a_in_active_bin: amounts_in_active_bin?.amount_a || '0',
  amount_b_in_active_bin: amounts_in_active_bin?.amount_b || '0',
  strategy_type: StrategyType.Spot,
  decimals_a: 6,
  decimals_b: 6,
  max_bin_slippage: 0.01,
  active_id,
  // If use_bin_infos is true, liquidity is allocated according to bin_infos; otherwise, it is calculated internally by the contract
  use_bin_infos: false,
}
const tx = sdk.Position.addLiquidityWithPricePayload(addOption)
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://cetus-1.gitbook.io/cetus-developer-docs/developer/via-sdk-v2/sdk-modules/cetusprotocol-dlmm-sdk/add-liquidity.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
