# Swap Base Out

Swaps tokens by specifying the output amount.

## Instruction

```rust
SwapInstructionBaseOut {
    max_amount_in: u64,
    amount_out: u64,
}
```

## Parameters

| Parameter       | Type  | Description                                                 |
| --------------- | ----- | ----------------------------------------------------------- |
| `max_amount_in` | `u64` | Maximum acceptable input token amount (slippage protection) |
| `amount_out`    | `u64` | Desired amount of output token                              |

## Account Setup

| #  | Account                         | Description                      | Derivation                                                                |
| -- | ------------------------------- | -------------------------------- | ------------------------------------------------------------------------- |
| 1  | Token program                   | SPL Token program                | `TOKEN_PROGRAM_ID`                                                        |
| 2  | AMM info                        | AMM account                      | `[program.toBuffer(), marketId.toBuffer(), "amm_associated_seed"]`        |
| 3  | AMM authority                   | AMM authority PDA                | `[Buffer.from("amm authority")]`                                          |
| 4  | AMM coin vault                  | Coin token vault                 | `[program.toBuffer(), marketId.toBuffer(), "coin_vault_associated_seed"]` |
| 5  | AMM PC vault                    | PC token (SOL) vault             | `[program.toBuffer(), marketId.toBuffer(), "pc_vault_associated_seed"]`   |
| 6  | User source                     | Source token account             | Depends on swap direction                                                 |
| 7  | User destination                | Destination token account        | Depends on swap direction                                                 |
| 8  | User source owner               | Transaction signer (User wallet) | -                                                                         |
| 9  | Coin mint                       | Coin token mint                  | Provided by user                                                          |
| 10 | Platform tax WSOL account       | Platform fee account             | Platform WSOL address                                                     |
| 11 | CC\* contribution WSOL account  | Community fund WSOL              | Associated account for fee destination                                    |
| 12 | CC\* contribution token account | Community fund token             | Associated account for fee destination                                    |

* CC - Community Contribution

## Function Logic

1. Verifies the transaction is signed by the token owner
2. Checks that the AMM is in a valid state for swapping
3. Determines swap direction (Coin2PC or PC2Coin) based on input and output token accounts
4. Calculates required input amount before fees using constant product formula
5. Adjusts input amount to account for fees
6. Verifies the required input is less than the maximum specified (slippage check)
7. For SC Bonding Curve tokens, calculates fee distribution among:
   * Platform fee
   * Community contribution (community fund)
   * Token burning
8. Executes the swap with appropriate fee handling based on token type and swap direction
9. Updates AMM state data with swap information

## Notes

* Swap Base Out is useful when a user wants an exact output amount
* Fee calculation differs based on token type and the token's configuration
* For SC Bonding Curve tokens, fees are distributed according to the token's specified parameters
* Burns are executed immediately during the swap transaction
* This function performs more complex calculations than Swap Base In due to working backwards from the desired output

## Swap Direction Setup

For selling tokens for SOL (Coin2PC):

* User source = User's token account: `getAssociatedTokenAddress(tokenMint, userWallet, false)`
* User destination = User's SOL account: `getAssociatedTokenAddress(NATIVE_MINT, userWallet, false)`

For buying tokens with SOL (PC2Coin):

* User source = User's SOL account: `getAssociatedTokenAddress(NATIVE_MINT, userWallet, false)`
* User destination = User's token account: `getAssociatedTokenAddress(tokenMint, userWallet, false)`

## Example Usage

```javascript
// Derive AMM accounts
const [ammAuthority] = PublicKey.findProgramAddressSync(
  [Buffer.from("amm authority")],
  COOLDEX_PROGRAM_ID
)

const [ammId] = PublicKey.findProgramAddressSync(
  [
    COOLDEX_PROGRAM_ID.toBuffer(),
    marketId.toBuffer(),
    Buffer.from("amm_associated_seed"),
  ],
  COOLDEX_PROGRAM_ID
)

const [ammCoinVault] = PublicKey.findProgramAddressSync(
  [
    COOLDEX_PROGRAM_ID.toBuffer(),
    marketId.toBuffer(),
    Buffer.from("coin_vault_associated_seed"),
  ],
  COOLDEX_PROGRAM_ID
)

const [ammPcVault] = PublicKey.findProgramAddressSync(
  [
    COOLDEX_PROGRAM_ID.toBuffer(),
    marketId.toBuffer(),
    Buffer.from("pc_vault_associated_seed"),
  ],
  COOLDEX_PROGRAM_ID
)

// Determine swap direction
const isSelling = true // Change based on swap direction

// User token accounts
const userTokenAccount = getAssociatedTokenAddressSync(tokenMint, wallet.publicKey, false)

const userWsolAccount = getAssociatedTokenAddressSync(
  NATIVE_MINT,
  wallet.publicKey,
  false
)

// Determine source and destination based on swap direction
const [userSource, userDestination] = isSelling
  ? [userTokenAccount, userWsolAccount]
  : [userWsolAccount, userTokenAccount]

// Create instruction data
const data = Buffer.alloc(17)
data.writeUInt8(10, 0) // SwapBaseOut instruction
data.writeBigUInt64LE(maxAmountIn, 1) // Maximum input amount
data.writeBigUInt64LE(amountOut, 9) // Desired output amount

// Community Contribution storage accounts
const commContribStorageWsol = await PublicKey.createWithSeed(
  tokenMint,
  "w",
  TOKEN_PROGRAM_ID
)

const commContribStorageToken = await PublicKey.createWithSeed(
  tokenMint,
  "t",
  TOKEN_PROGRAM_ID
)

const swapBaseOutIx = new TransactionInstruction({
  programId: COOLDEX_PROGRAM_ID,
  keys: [
    { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
    { pubkey: ammId, isSigner: false, isWritable: true },
    { pubkey: ammAuthority, isSigner: false, isWritable: false },
    { pubkey: ammCoinVault, isSigner: false, isWritable: true },
    { pubkey: ammPcVault, isSigner: false, isWritable: true },
    { pubkey: userSource, isSigner: false, isWritable: true },
    { pubkey: userDestination, isSigner: false, isWritable: true },
    { pubkey: wallet.publicKey, isSigner: true, isWritable: false },
    { pubkey: tokenMint, isSigner: false, isWritable: true },
    { pubkey: AMM_FEE_DESTINATION, isSigner: false, isWritable: true },
    { pubkey: commContribStorageWsol, isSigner: false, isWritable: true },
    { pubkey: commContribStorageToken, isSigner: false, isWritable: true },
  ],
  data: data,
})
```


---

# 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.something.cool/cooldex/functions/swap-base-out.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.
