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

# Create Fee Claim Transaction

> POST /fee-claim/claim - Create unsigned transaction for claiming Meteora DAMM v2 pool fees

## Overview

Creates an unsigned transaction for claiming accumulated fees from a Meteora DAMM v2 (Dynamic AMM) pool. The API validates available fees, builds a combined transaction that claims fees and transfers 70% to the configured destination address, and returns the transaction ready for user signing.

<Note>
  **Important**: This endpoint only claims fees from the **first position** in the pool to keep transaction size manageable. If multiple positions exist, subsequent calls are needed to claim from other positions.
</Note>

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.zcombinator.io/fee-claim/claim \
    -H "Content-Type: application/json" \
    -d '{
      "payerPublicKey": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM"
    }'
  ```

  ```javascript fetch theme={null}
  const response = await fetch('https://api.zcombinator.io/fee-claim/claim', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      payerPublicKey: "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM"
    })
  });

  const result = await response.json();
  ```

  ```python requests theme={null}
  import requests

  data = {
      "payerPublicKey": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM"
  }

  response = requests.post(
      'https://api.zcombinator.io/fee-claim/claim',
      json=data,
      headers={'Content-Type': 'application/json'}
  )

  result = response.json()
  ```
</CodeGroup>

## Request Parameters

<ParamField body="payerPublicKey" type="string" required>
  Base58 encoded public key of the wallet that will pay transaction fees. This wallet only covers network transaction costs and cannot redirect claimed fees.
</ParamField>

## Response

<ResponseField name="success" type="boolean">
  Indicates if the operation was successful
</ResponseField>

<ResponseField name="transaction" type="string">
  Base58 encoded unsigned transaction that needs to be signed by the fee payer
</ResponseField>

<ResponseField name="requestId" type="string">
  Unique identifier for this fee claim request (needed for confirmation)
</ResponseField>

<ResponseField name="poolAddress" type="string">
  Address of the Meteora DAMM v2 pool
</ResponseField>

<ResponseField name="tokenAMint" type="string">
  Mint address of Token A in the pool
</ResponseField>

<ResponseField name="tokenBMint" type="string">
  Mint address of Token B in the pool
</ResponseField>

<ResponseField name="isTokenBNativeSOL" type="boolean">
  Whether Token B is native SOL (unwrapped after claim)
</ResponseField>

<ResponseField name="totalPositions" type="number">
  Total number of positions owned by the LP owner in this pool
</ResponseField>

<ResponseField name="claimingPosition" type="number">
  Position number being claimed (always 1 for this endpoint)
</ResponseField>

<ResponseField name="instructionsCount" type="number">
  Number of instructions in the transaction
</ResponseField>

<ResponseField name="estimatedFees" type="object">
  Object containing fee estimates with the following fields:

  * `tokenA` (string): Total Token A fees to be claimed
  * `tokenB` (string): Total Token B fees to be claimed
  * `tokenATransfer` (string): Token A amount to be transferred (70%)
  * `tokenBTransfer` (string): Token B amount to be transferred (70%)
</ResponseField>

<ResponseField name="message" type="string">
  Instructions for the next step in the process
</ResponseField>

### Success Response

```json theme={null}
{
  "success": true,
  "transaction": "4MzR7dxJNJRVP1Q6k7Y3j8X...",
  "requestId": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
  "poolAddress": "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C",
  "tokenAMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  "tokenBMint": "So11111111111111111111111111111111111111112",
  "isTokenBNativeSOL": true,
  "totalPositions": 3,
  "claimingPosition": 1,
  "instructionsCount": 8,
  "estimatedFees": {
    "tokenA": "1000000",
    "tokenB": "500000000",
    "tokenATransfer": "700000",
    "tokenBTransfer": "350000000"
  },
  "message": "Sign this transaction and submit to /fee-claim/confirm (Token B will be transferred as native SOL)"
}
```

## Error Responses

<AccordionGroup>
  <Accordion title="400 - Missing Parameters">
    ```json theme={null}
    {
      "error": "Missing required field: payerPublicKey"
    }
    ```
  </Accordion>

  <Accordion title="400 - Invalid Public Key">
    ```json theme={null}
    {
      "error": "Invalid payerPublicKey format"
    }
    ```

    The provided public key is not a valid Solana address.
  </Accordion>

  <Accordion title="404 - No Positions Found">
    ```json theme={null}
    {
      "error": "No positions found for the LP owner in this pool"
    }
    ```

    The protocol wallet does not have any LP positions in the configured pool.
  </Accordion>

  <Accordion title="400 - No Fees Available">
    ```json theme={null}
    {
      "error": "No fees available to claim"
    }
    ```

    All fees have already been claimed or no fees have accumulated yet.
  </Accordion>

  <Accordion title="500 - Configuration Error">
    ```json theme={null}
    {
      "error": "Server configuration incomplete. Missing required environment variables."
    }
    ```

    Required environment variables (RPC\_URL, DAMM\_POOL\_ADDRESS, PROTOCOL\_PRIVATE\_KEY, FEE\_DESTINATION\_ADDRESS) are not configured.
  </Accordion>

  <Accordion title="500 - Transaction Creation Failed">
    ```json theme={null}
    {
      "error": "Failed to create fee claim transaction"
    }
    ```
  </Accordion>
</AccordionGroup>

## Process Flow

This endpoint performs several validations and transaction building steps:

<Steps>
  <Step title="Validate Parameters">
    Ensures payerPublicKey is provided and is a valid Solana address
  </Step>

  <Step title="Validate Environment">
    Checks that required environment variables are configured (RPC\_URL, DAMM\_POOL\_ADDRESS, PROTOCOL\_PRIVATE\_KEY, FEE\_DESTINATION\_ADDRESS)
  </Step>

  <Step title="Initialize Connection">
    Connects to Solana RPC and loads the LP owner keypair
  </Step>

  <Step title="Fetch Pool State">
    Retrieves the current state of the Meteora DAMM v2 pool
  </Step>

  <Step title="Get User Positions">
    Fetches all LP positions owned by the protocol wallet
  </Step>

  <Step title="Calculate Unclaimed Fees">
    Uses Meteora SDK to calculate accurate unclaimed fees for all positions
  </Step>

  <Step title="Build Combined Transaction">
    Creates a transaction with:

    * ATA creation instructions (if needed)
    * Fee claim instruction (first position only)
    * Transfer instructions (70% to destination, 30% remains with LP owner)
  </Step>

  <Step title="Handle Native SOL">
    If Token B is wrapped SOL, the transaction includes native SOL transfer logic (Meteora automatically unwraps wSOL to native SOL)
  </Step>

  <Step title="Store Transaction Data">
    Temporarily stores transaction details with requestId for confirmation step
  </Step>

  <Step title="Return Unsigned Transaction">
    Returns the Base58 encoded transaction for user signing
  </Step>
</Steps>

## Fee Distribution

The claimed fees are automatically split:

* **70%**: Transferred to the configured destination address (FEE\_DESTINATION\_ADDRESS)
* **30%**: Remains with the LP owner wallet

This split is hardcoded and cannot be modified by the fee payer.

## Native SOL Handling

<Info>
  **Special handling for wrapped SOL (wSOL)**:

  When Token B is the native SOL mint (So11111111111111111111111111111111111111112):

  1. Meteora automatically unwraps wSOL to native SOL during the claim
  2. No token account is created for Token B
  3. The 70% transfer uses `SystemProgram.transfer` instead of SPL token transfer
  4. Fees are received directly as native SOL in the wallet
</Info>

## Request ID

The `requestId` is essential for the confirmation step:

* **Format**: Random 16-byte hex string
* **Expiration**: Automatically cleaned up after 15 minutes
* **Required**: Must be provided to [`/fee-claim/confirm`](/api-reference/fee-claim/confirm)

## Rate Limiting

This endpoint is subject to rate limiting:

* **10 requests** per 5-minute window per IP
* Returns HTTP 429 when limit exceeded with message: "Too many fee claim requests, please wait a moment."

## Security Considerations

<Warning>
  **No authorization required**:

  * Fee destinations are hardcoded in environment variables
  * Transaction validation ensures funds can ONLY go to configured addresses
  * Fee payer only covers transaction costs, cannot redirect fees
  * This allows anyone to trigger fee claims for the protocol
</Warning>

## Next Steps

After receiving the unsigned transaction:

1. **Deserialize** the transaction using `@solana/web3.js`
2. **Sign** the transaction with your wallet (fee payer)
3. **Submit** the signed transaction to [`/fee-claim/confirm`](/api-reference/fee-claim/confirm)

## Transaction Storage

Transaction data is stored temporarily in memory:

* **Storage Duration**: 10 minutes (validation) to 15 minutes (cleanup)
* **Cleanup**: Automatic cleanup every 5 minutes
* **Expiration**: You must call `/fee-claim/confirm` within the time window

## Position Claiming

<Note>
  **Multiple positions**: If `totalPositions > 1`, you need to call this endpoint multiple times to claim fees from all positions. Each call claims fees from the first unclaimed position.
</Note>
