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

# Build Withdrawal Transaction

> POST /damm/withdraw/build - Create unsigned transaction for withdrawing liquidity from Meteora DAMM v2 pool

## Overview

Creates an unsigned transaction for withdrawing liquidity from a Meteora DAMM v2 (Dynamic AMM) pool. The API validates available liquidity, builds a combined transaction that removes liquidity and transfers withdrawn tokens to the manager wallet, and returns the transaction ready for manager wallet signing.

<Warning>
  **Manager-only operation**: This endpoint requires the manager wallet to sign and submit the transaction. The manager wallet must be configured via the `MANAGER_WALLET` environment variable.
</Warning>

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.zcombinator.io/damm/withdraw/build \
    -H "Content-Type: application/json" \
    -d '{
      "withdrawalPercentage": 12.5
    }'
  ```

  ```javascript fetch theme={null}
  const response = await fetch('https://api.zcombinator.io/damm/withdraw/build', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      withdrawalPercentage: 12.5
    })
  });

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

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

  data = {
      "withdrawalPercentage": 12.5
  }

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

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

## Request Parameters

<ParamField body="withdrawalPercentage" type="number" required={true}>
  Percentage of unlocked liquidity to withdraw (`0 < value <= 15`). For example, `12.5` withdraws 12.5% of available liquidity. **Maximum 15% to prevent excessive liquidity removal.**
</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 manager wallet
</ResponseField>

<ResponseField name="requestId" type="string">
  Unique identifier for this withdrawal 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 (handled specially in transfers)
</ResponseField>

<ResponseField name="withdrawalPercentage" type="number">
  The withdrawal percentage requested
</ResponseField>

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

<ResponseField name="estimatedAmounts" type="object">
  Object containing estimated withdrawal amounts:

  * `tokenA` (string): Estimated Token A amount to be withdrawn
  * `tokenB` (string): Estimated Token B amount to be withdrawn
  * `liquidityDelta` (string): Amount of liquidity being removed
</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,
  "withdrawalPercentage": 12.5,
  "instructionsCount": 7,
  "estimatedAmounts": {
    "tokenA": "5000000",
    "tokenB": "2500000000",
    "liquidityDelta": "1000000"
  },
  "message": "Sign this transaction with the manager wallet and submit to /damm/withdraw/confirm"
}
```

## Error Responses

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

  <Accordion title="400 - Invalid Withdrawal Percentage">
    ```json theme={null}
    {
      "error": "withdrawalPercentage must be a number between 0 and 15"
    }
    ```

    The withdrawal percentage must be greater than 0 and not exceed 15. This limit prevents excessive liquidity removal in a single transaction.
  </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 Unlocked Liquidity">
    ```json theme={null}
    {
      "error": "No unlocked liquidity in position"
    }
    ```

    The position has no available liquidity to withdraw (all liquidity may be locked).
  </Accordion>

  <Accordion title="400 - Withdrawal Too Small">
    ```json theme={null}
    {
      "error": "Withdrawal amount too small"
    }
    ```

    The calculated withdrawal amount is too small to process (rounds to zero).
  </Accordion>

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

    The server is not properly configured to process withdrawal requests.
  </Accordion>

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

## Process Flow

This endpoint performs several steps to build the withdrawal transaction:

<Steps>
  <Step title="Validate Parameters">
    Ensures withdrawalPercentage is provided and is a valid number between 0 and 15 (maximum 15% to prevent excessive liquidity removal)
  </Step>

  <Step title="Validate Server Configuration">
    Checks that the server is properly configured to process withdrawal requests
  </Step>

  <Step title="Verify Authorization">
    Validates that the manager wallet is authorized to perform withdrawals
  </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 (uses first position)
  </Step>

  <Step title="Calculate Withdrawal Amount">
    Calculates liquidityDelta based on the withdrawal percentage and available unlocked liquidity
  </Step>

  <Step title="Calculate Token Amounts">
    Calculates the exact token amounts that will be withdrawn based on current pool state
  </Step>

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

    * Removes liquidity from the pool position
    * Transfers all withdrawn tokens to the manager wallet
    * Creates any needed token accounts
  </Step>

  <Step title="Handle Native SOL">
    If Token B is native SOL, uses SystemProgram.transfer instead of SPL token transfer
  </Step>

  <Step title="Generate Request ID">
    Creates a unique request ID for tracking this withdrawal request
  </Step>

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

## Withdrawal Percentage Calculation

The withdrawal amount is calculated as:

```
liquidityDelta = unlockedLiquidity * (withdrawalPercentage * 1000) / 100000
```

This calculation ensures precision while working with integer arithmetic.

<Note>
  **First position only**: This endpoint withdraws from the first position in the pool. If multiple positions exist, you need to call this endpoint multiple times to withdraw from other positions.
</Note>

## 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 withdrawal
  2. No token account is created for Token B for the LP owner
  3. Transfers use `SystemProgram.transfer` instead of SPL token transfer
  4. Withdrawn SOL is received directly as native SOL in the manager 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 [`/damm/withdraw/confirm`](/api-reference/damm-liquidity/withdraw-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 liquidity requests, please wait a moment."

## Security Considerations

<Warning>
  **Manager authorization required**:

  * Only the configured manager wallet can sign and confirm withdrawals
  * Withdrawn tokens always go to the manager wallet
  * LP owner's signature is added automatically by the API
  * This prevents unauthorized liquidity withdrawals
</Warning>

## Next Steps

After receiving the unsigned transaction:

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

## Request Expiration

Withdrawal requests expire after a period of time:

* **Validity**: You must call `/damm/withdraw/confirm` within 10 minutes
* **After expiration**: You'll need to create a new withdrawal request

## Related Endpoints

* [`/damm/withdraw/confirm`](/api-reference/damm-liquidity/withdraw-confirm) - Confirm and submit the withdrawal transaction
* [`/damm/deposit/build`](/api-reference/damm-liquidity/deposit-build) - Build deposit transaction
