> For the complete documentation index, see [llms.txt](https://titan-exchange.gitbook.io/titan/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/swap-v2-vs-v3.md).

# Swap V2 vs Swap V3

What Swap V3 changes over V2 and how to opt in.

Swap V3 is the newer version of the Titan Exchange Router. V2 is the current default; V3 is opt-in via `titanSwapVersion: 3`.

{% hint style="warning" %}
**V3 is the default.** Requests without `titanSwapVersion` use V3. V2 remains available as an explicit opt-in (`titanSwapVersion: 2`). See [Migrating to V3](#migrating-to-v3) below.
{% endhint %}

## What's new in V3

**Account handling moved inside the instruction.** Output ATA creation and wSOL wrapping/unwrapping are handled inside the swap instruction itself, so a V3 route returns a single consolidated swap instruction where V2 returned several separate ones. This reduces the number of instructions you assemble into the transaction.

**Separate fee payer (`payer`).** A distinct account can fund all SOL-denominated costs — network fees, ATA rent (wSOL wrap, output ATA), and rent refunds — instead of the user paying them. The payer must co-sign the transaction. Defaults to the user if not set. Enables sponsored / gasless-style swap flows.

**Positive-slippage capture (`positiveSlippageFeeReceiver`).** When realized output beats the quoted amount, the surplus can be skimmed to a designated account, capped at 10 bps of the output. The receiver must be an existing token account of the output mint. Anything above the cap stays with the user.

**Keep output as wSOL (`outputWsol`).** When the output mint is wrapped SOL (`So11111111111111111111111111111111111111112`), the router unwraps the result to native SOL by default. Set `outputWsol: true` to leave the output as the wSOL SPL token instead — useful when the next step in your flow expects a token account rather than native lamports. Boolean, defaults to `false`. Only has an effect when `outputMint` is wSOL.

```jsonc
{
  "transaction": {
    "userPublicKey": "72neGwRAi6QWsFQjy3PkDuYBC5GNCRwC2aUMGcrkoJuP",
    "outputWsol": true
  }
}
```

## Selecting a version

V3 is selected per request via the `titanSwapVersion` field in `TransactionParams`. Leave it unset for V2 (the default); set it to `3` to opt into V3 and unlock `payer`, `positiveSlippageFeeReceiver`, and `outputWsol`.

```jsonc
{
  "transaction": {
    "userPublicKey": "72neGwRAi6QWsFQjy3PkDuYBC5GNCRwC2aUMGcrkoJuP",
    "titanSwapVersion": 3
  }
}
```

> `titanSwapVersion` is the integer `3`, **not** the string `"V3"`. A string is rejected with `Failed to deserialize query string: titanSwapVersion: invalid digit found in string`.

## Pinning to V2

If you are not ready to migrate, set `titanSwapVersion: 2` explicitly. Requests that pin the version this way keep using V2 until it is fully retired.

```jsonc
{
  "transaction": {
    "userPublicKey": "72neGwRAi6QWsFQjy3PkDuYBC5GNCRwC2aUMGcrkoJuP",
    "titanSwapVersion": 2
  }
}
```

{% hint style="info" %}
Pinning to V2 is a stopgap, not a long-term position. Treat the pin as a way to buy migration time — not to stay on V2 indefinitely.
{% endhint %}

## Migrating to V3

V3 is the default, so requests without `titanSwapVersion` already use it. If you pinned `titanSwapVersion: 2`, remove the field or set it to `3` to move.

V3 adds three optional fields in `TransactionParams`. None are required to migrate — adopt them only if you need what they provide:

* **`payer`** — a separate account to fund the SOL-denominated costs of the swap. Must co-sign the transaction. Defaults to the user's public key if unset.
* **`positiveSlippageFeeReceiver`** — the account that receives any positive-slippage surplus.
* **`outputWsol`** — leave the output as wrapped SOL instead of unwrapping to native SOL, when the output mint is wSOL. Defaults to `false`.

If you build the transaction yourself from the route's `instructions` and `addressLookupTables`, note that the V3 instruction set differs from V2 — a V3 route returns a single consolidated swap instruction where V2 returned several. Rebuild from the returned `instructions` rather than assuming the V2 layout.

When reading quotes, set the transaction's compute-unit limit from the quote's `computeUnitsSafe` — the server's recommended value with a buffer — rather than a hard-coded number.

### Migration checklist

1. Set `titanSwapVersion: 3` on your swap requests.
2. Adopt `payer`, `positiveSlippageFeeReceiver`, or `outputWsol` only if your flow needs them.
3. If you set compute-unit limits manually, use the quote's `computeUnitsSafe`.
4. Drop `titanSwapVersion` entirely — V3 is the default.

## Comparison

|                                | Swap V2                               | Swap V3                                                            |
| ------------------------------ | ------------------------------------- | ------------------------------------------------------------------ |
| Status                         | Opt-in (`titanSwapVersion: 2`)        | Default                                                            |
| ATA creation + SOL wrap/unwrap | Separate instructions around the swap | Handled inside the swap instruction (one consolidated instruction) |
| Separate fee payer             | No                                    | Yes (`payer`, must co-sign)                                        |
| Positive-slippage capture      | No                                    | Yes (≤ 10 bps, output-mint token account)                          |
| Keep output as wSOL            | No                                    | Yes (`outputWsol`)                                                 |
