> ## Documentation Index
> Fetch the complete documentation index at: https://docs.meteora.ag/llms.txt
> Use this file to discover all available pages before exploring further.

# Integrate with DAMM v2

> Everything you need to know to integrate with Meteora's DAMM v2 Program

Trading Terminals can easily integrate with Meteora DAMM v2 by following this guide that explains in detail how to get the necessary data from indexing the DAMM v2 program.

## Total Fees

```
totalFees = baseFees + dynamicFees
```

### Base Fees

Base Fees includes either a Flat Fee, Fee Scheduler, Rate Limiter, or Fee Market Cap Scheduler.

<Note>
  `BaseFeeMode` can be enums 0, 1, 2, 3, or 4.

  * 0 = Linear Fee Time Scheduler
  * 1 = Exponential Fee Time Scheduler
  * 2 = Rate Limiter
  * 3 = Linear Fee Market Cap Scheduler
  * 4 = Exponential Fee Market Cap Scheduler
</Note>

#### Decoding BaseFee

The `baseFee.data` field is a `number[]` (byte array) that requires decoding when indexed. The decoder type depends on the **data source** and **`baseFeeMode`**.

**From `EvtInitializePool` event** (Borsh serialization, 30 bytes):

* `baseFeeMode` 0-1: Use `BorshFeeTimeScheduler`
* `baseFeeMode` 2: Use `BorshFeeRateLimiter`
* `baseFeeMode` 3-4: Use `BorshFeeMarketCapScheduler`

**From `poolState` account** (Pod-aligned serialization, 32 bytes):

* `baseFeeMode` 0-1: Use `PodAlignedFeeTimeScheduler`
* `baseFeeMode` 2: Use `PodAlignedFeeRateLimiter`
* `baseFeeMode` 3-4: Use `PodAlignedFeeMarketCapScheduler`

#### Flat Fee

You can fetch the flat fee directly from the `cliffFeeNumerator` in the `baseFee` object if all other parameters are 0.

```typescript theme={"system"}
// Example - Flat fee
baseFee: {
  cliffFeeNumerator: 10000000,        // 1% flat fee
  baseFeeMode: 0,
  numberOfPeriod: 0,
  periodFrequency: 0,
  reductionFactor: 0
}
```

<Warning>
  The Fee Scheduler depends on the `poolState.activationType`.

  * If the `poolState.activationType == 0`, then `numberOfPeriod` and `periodFrequency` is calculated in `SLOT == 400ms`
  * If the `poolState.activationType == 1`, then `numberOfPeriod` and `periodFrequency` is calculated in `SECONDS == 1000ms`
</Warning>

#### Fee Time Scheduler

* For Fee Time Scheduler, the fee reduces over time based on the scheduler configuration.

* `baseFeeMode` can be 0 (Linear) or 1 (Exponential).

```typescript theme={"system"}
interface FeeTimeScheduler {
    cliffFeeNumerator: BN;              // Starting fee numerator (e.g., 500000000 = 50%)
    baseFeeMode: number;                // 0 = Linear, 1 = Exponential
    numberOfPeriod: number;             // Number of fee reduction periods
    periodFrequency: BN;                // Time between periods (slots or seconds based on activationType)
    reductionFactor: BN;                // Fee reduction per period
}
```

<Note>You can refer to the math formula for the Fee Time Scheduler [here](/anti-sniper-suite/fee-time-scheduler/fee-time-scheduler-math)</Note>

Here are some examples of how the Fee Time Scheduler works:

```typescript theme={"system"}
// Fee Time Scheduler: 50% reduce to 1% in 10 minutes linearly
{
  cliffFeeNumerator: new BN(500000000),   // 50% starting fee
  baseFeeMode: 0,                         // Linear mode
  numberOfPeriod: 100,                    // 100 periods
  periodFrequency: new BN(1),             // Time between periods
  reductionFactor: new BN(4900000),       // Reduction factor per period
}
```

```typescript theme={"system"}
// Fee Time Scheduler: 50% reduce to 1% in 10 minutes exponentially
{
  cliffFeeNumerator: new BN(500000000),   // 50% starting fee
  baseFeeMode: 1,                         // Exponential mode
  numberOfPeriod: 100,                    // 60 periods
  periodFrequency: new BN(1),             // Time between periods
  reductionFactor: new BN(383),           // Reduction factor per period
}
```

#### Rate Limiter

* For Rate Limiter, the fee increases exponentially based on trade size to prevent large trades from manipulating the market.

* `baseFeeMode` can only be 2.

<Warning>
  When integrating swaps with Rate Limiter pools (`baseFeeMode == 2`), you must include `SYSVAR_INSTRUCTIONS_PUBKEY` in the remaining accounts of the swap instruction.
</Warning>

```typescript theme={"system"}
interface FeeRateLimiter {
    cliffFeeNumerator: BN;              // Base fee numerator (e.g., 10000000 = 1%)
    baseFeeMode: number;                // 2 = Rate Limiter
    feeIncrementBps: number;            // Fee increment in basis points per reference amount
    maxLimiterDuration: number;         // Maximum duration for rate limiter (slots or seconds)
    maxFeeBps: number;                  // Maximum fee cap in basis points
    referenceAmount: BN;                // Reference amount for fee calculation
}
```

<Note>You can refer to the math formula for the Rate Limiter [here](/anti-sniper-suite/rate-limiter/rate-limiter-math)</Note>

Here are some examples of how the Rate Limiter works:

```typescript theme={"system"}
// Rate Limiter: Starts at 1% fee -> Exponential increase in fee for 10 slots based on trade size
// 0.5 SOL trade
// fee = 0.5 SOL * 0.1% = 0.0005 SOL
// 1.5 SOL trade
// fee = 1 SOL * 0.1% + 0.5 SOL * 0.2% = 0.002 SOL
// 3 SOL trade
// fee = 1 SOL * 0.1% + 1 SOL * 0.2% + 1 SOL * 0.3% = 0.006 SOL
{
   cliffFeeNumerator: new BN(10000000),  // Base fee numerator (1%)
   baseFeeMode: 2,                       // Rate limiter mode
   feeIncrementBps: 10,                  // Fee increment per reference amount in basis points
   maxFeeBps: 5000,                      // Max fee cap in basis points (50%)
   referenceAmount: new BN(1000000000),  // Reference amount in lamports (1 SOL)
   maxLimiterDuration: 10,               // Duration in slots/seconds
}
```

#### Fee Market Cap Scheduler

* Fee Market Cap Scheduler reduces fees based on **price movement (market cap growth)** rather than time. This is different from Fee Time Scheduler which reduces fees over time regardless of price action.

* `baseFeeMode` can be 3 (Linear) or 4 (Exponential).

```typescript theme={"system"}
interface FeeMarketCapScheduler {
    cliffFeeNumerator: BN;              // Starting fee numerator (e.g., 500000000 = 50%)
    baseFeeMode: number;                // 3 = Linear, 4 = Exponential
    numberOfPeriod: number;             // Number of fee reduction periods
    sqrtPriceStepBps: number;           // Sqrt price step in bps to advance one period
    schedulerExpirationDuration: number; // Duration after which scheduler expires (slots or seconds)
    reductionFactor: BN;                // Fee reduction per period
}
```

<Note>You can refer to the detailed math formula for the Fee Market Cap Scheduler [here](/anti-sniper-suite/fee-market-cap-scheduler/fee-market-cap-scheduler-math)</Note>

Here are some examples of how the Fee Market Cap Scheduler works:

```typescript theme={"system"}
// Fee Market Cap Scheduler: 50% starting fee, reduces linearly based on price growth
{
  cliffFeeNumerator: new BN(500000000),  // 50% starting fee
  baseFeeMode: 3,                        // Linear mode
  numberOfPeriod: 100,                   // 100 periods
  sqrtPriceStepBps: 100,                 // 1% sqrt price step per period
  schedulerExpirationDuration: 86400,    // 24 hours expiration
  reductionFactor: new BN(4950000),      // Linear reduction factor
}
```

```typescript theme={"system"}
// Fee Market Cap Scheduler: 50% starting fee, reduces exponentially based on price growth
{
  cliffFeeNumerator: new BN(500000000),  // 50% starting fee
  baseFeeMode: 4,                        // Exponential mode
  numberOfPeriod: 100,                   // 100 periods
  sqrtPriceStepBps: 100,                 // 1% sqrt price step per period
  schedulerExpirationDuration: 86400,    // 24 hours expiration
  reductionFactor: new BN(390),          // Exponential reduction factor (bps)
}
```

### Dynamic Fees (Variable Fee)

You can refer to the Dynamic Fee calculation [here](/overview/products/damm-v2/pool-fees-calculation#dynamic-fee-variable-fee)

## Pool Version (fee\_version)

The `fee_version` field on a pool state indicates its version. Pool version determines the maximum allowed fee.

| `fee_version` | Max Fee |
| ------------- | ------- |
| 0 (V0)        | 50%     |
| 1 (V1)        | 99%     |

<Info>
  All newly created pools are V1.
</Info>

## Plotting Charts

<Danger>Using Transfer logs from Swap transactions is not the correct way of getting the token price as we have Anti-Sniper Suite features that can cause huge fee deductions from `TokenAmountIn` OR `TokenAmountOut`. Plotting the token chart price from these will lead to a very ugly chart.</Danger>

The correct way is to fetch the `EvtSwap2` CPI logs from the Swap transaction.

<Note>`EvtSwap` is an older version of the swap CPI logs and might be deprecated in the future. Use `EvtSwap2` instead.</Note>

Because of the Anti-Sniper Suite features, you will have to apply the following checks to get the correct token price either before/after the fee deduction.

\[1.1] Firstly, you will need to identify where the fees are coming from (either from input or output):

```
feeOnInput: (collectFeeMode == 1 && tradeDirection == 1) || (collectFeeMode == 2 && tradeDirection == 1) ? true : false
```

\[1.2] Next, calculate the amount and plot price depending on where the fees are coming from (either from input or output):

```
if (feeOnInput): price = excludedFeeInputAmount / outputAmount

if (!feeOnInput): price = excludedFeeInputAmount / (outputAmount + tradingFee + protocolFee + referralFee + compoundingFee)
```

<Warning>
  **Breaking change in v0.2.0:** `EvtSwap2` no longer contains a `partner_fee` field. It has been replaced by `compounding_fee`. Update any integrations that previously read `partner_fee` from swap CPI logs to use `compounding_fee` instead.

  The total trading fee is now: `tradingFee = claimingFee + compoundingFee`
</Warning>

### Collect Fee Mode 2 (Compounding)

When `collectFeeMode == 2`, the pool operates in **Compounding** mode. This affects how you interpret swap events and price calculations:

* Fees are always collected in Token B (quote token), regardless of trade direction.
* For B→A trades (`tradeDirection == 1`), fees are deducted from the input amount (`feeOnInput = true`).
* A percentage of the fee (configured by `compounding_fee_bps`) is automatically reinvested back into the pool reserves rather than being claimable by LPs. This portion appears as `compounding_fee` in `EvtSwap2`.
* The pool uses a constant-product formula (no concentrated liquidity range) in this mode.

**Fee collection summary by mode and direction:**

| `collectFeeMode` | A→B trade         | B→A trade                        |
| ---------------- | ----------------- | -------------------------------- |
| 0 (BothToken)    | Fee on B (output) | Fee on A (output)                |
| 1 (OnlyB)        | Fee on B (output) | Fee on B (input)                 |
| 2 (Compounding)  | Fee on B (output) | Fee on B (input) + auto-compound |

**`SwapResult2` fields (v0.2.0+):**

```typescript theme={"system"}
interface SwapResult2 {
  included_fee_input_amount: BN;   // Input amount including fee (when feeOnInput)
  excluded_fee_input_amount: BN;   // Input amount excluding fee
  amount_left: BN;                 // Remaining amount after swap
  output_amount: BN;               // Output amount to recipient
  next_sqrt_price: BN;             // Pool sqrt price after swap
  claiming_fee: BN;                // Fee claimable by LPs
  compounding_fee: BN;             // Fee auto-reinvested into reserves (replaces partner_fee)
  protocol_fee: BN;                // Fee taken by protocol
  referral_fee: BN;                // Fee taken by referral account
}
```

## Trading Volume

Track from Swap CPI logs:

```
// Depending on Trade Direction:
trading_volume += actualAmountIn * token_price
```

## Liquidity

In the DAMM v2 pool, the liquidity is fetched from the `tokenAVault` and `tokenBVault` of the DAMM v2 pool.

```
liquidity = tokenAVault * tokenAPrice + tokenBVault * tokenBPrice
```

## Locked or Vested Liquidity

In DAMM v2, there are 3 different modes for liquidity:

1. `lockedLiquidity` - which means that the liquidity is permanently locked
2. `vestedLiquidity` - which means that the liquidity is vestedLiquidity
3. `unlockedLiquidity` - which means that the liquidity is unlocked and claimable

You can use our DAMM v2 API [endpoint](/api-reference/pools/get_pool_vesting_list) that tracks pool positions and show accurately whether the liquidity is locked or not on your trading terminal.

### How to Identify Launchpads Using DAMM v2

You can ping us on Discord to get a list of all launchpads configuration who are launching on DAMM v2 directly so that you can index them on your trading terminal.

<Note>Open a ticket on [discord](https://discord.gg/meteora) to get access to the list.</Note>

## Referral Account

* For trading terminals, we have a feature that enables trading terminals to earn referral fees from all swaps that happen on our Meteora DAMM v2 program as long as they were swapped through your trading terminal.
* For referral fees, include your referral token account in the swap instruction and you will receive **20%** of the protocol fee for all swaps.
