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

# Solana DEX Trades

> Use the solana.dex_swaps Turbo dataset to stream normalized swap events from major Solana DEXes.

## Overview

`solana.dex_swaps` is a Turbo-only curated dataset that emits one normalized row per DEX swap across the major Solana AMMs and bonding-curve programs. Each row is a fully decoded swap event with the bought/sold token, amounts (both raw and decimal-scaled), the underlying program, and the transaction context needed to trace the swap back on-chain.

<Note>
  This dataset is exclusive to [Turbo](/turbo-pipelines/introduction) and is not available in Mirror.
</Note>

Use it when you want to:

* Track swap volume, prices, or flows across multiple Solana DEXes without decoding each program's instructions yourself.
* Attribute swaps to routers/aggregators (for example, Jupiter) versus direct DEX interactions.
* Join raw and decimal-scaled amounts alongside the on-chain transaction signature and slot.

## Quick start

Scope the source to the DEXes you care about with `filter.program_ids` (program IDs) and `options.dex` (human-readable labels). Both accept a comma-separated string.

```yaml theme={null}
sources:
  dex_swaps:
    type: dataset
    dataset_name: solana.dex_swaps
    version: 1.0.0
    start_block: 426725306
    filter:
      program_ids: whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc,CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK
    options:
      dex: raydium_clmm,orca_whirlpool
```

See [Solana Sources](/turbo-pipelines/sources/solana) for general Solana source configuration (`start_block`, `block_ranges`, filters, checkpoints).

## Supported DEXes and program IDs

The dataset currently decodes swap events from the following programs. The `project` column is the human-readable label (use in `options.dex`); `project_main_id` carries the raw on-chain program ID (use in `filter.program_ids`).

| DEX (`project`)   | Program ID (`project_main_id`)                 |
| ----------------- | ---------------------------------------------- |
| `meteora_damm_v1` | `Eo7WjKq67rjJQSZxS6z3YkapzY3eMj6Xy8X5EQVn5UaB` |
| `meteora_damm_v2` | `cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG`  |
| `raydium_clmm`    | `CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK` |
| `raydium_cpmm`    | `CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C` |
| `orca_whirlpool`  | `whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc`  |
| `pump_amm`        | `pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA`  |
| `pumpfun`         | `6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P`  |

## Schema

All amounts describe a single side of the trade: the *bought* token is what the trader received, the *sold* token is what they gave up.

| Column                      | Type    | Nullable | Description                                                                                                                                  |
| --------------------------- | ------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                        | string  | no       | Unique swap id.                                                                                                                              |
| `project`                   | string  | yes      | Human-readable DEX label (for example, `raydium_clmm`, `pump_amm`).                                                                          |
| `version`                   | uint8   | yes      | DEX/event schema version.                                                                                                                    |
| `block_timestamp`           | uint64  | no       | Unix timestamp (seconds) of the block.                                                                                                       |
| `block_slot`                | uint64  | no       | Solana slot the transaction landed in.                                                                                                       |
| `trade_source`              | string  | no       | `direct` when the swap is a top-level instruction; otherwise the program ID of the router/aggregator (for example, Jupiter) that invoked it. |
| `token_bought_amount`       | float64 | no       | Amount received, scaled by `token_bought_decimals` (human units).                                                                            |
| `token_sold_amount`         | float64 | no       | Amount paid, scaled by `token_sold_decimals` (human units).                                                                                  |
| `token_bought_amount_raw`   | uint64  | no       | Amount received in raw base units (unscaled integer).                                                                                        |
| `token_sold_amount_raw`     | uint64  | no       | Amount paid in raw base units (unscaled integer).                                                                                            |
| `token_bought_mint_address` | string  | no       | SPL mint address of the token received.                                                                                                      |
| `token_sold_mint_address`   | string  | no       | SPL mint address of the token paid.                                                                                                          |
| `token_bought_decimals`     | uint8   | no       | Decimals of the bought mint.                                                                                                                 |
| `token_sold_decimals`       | uint8   | no       | Decimals of the sold mint.                                                                                                                   |
| `project_main_id`           | string  | no       | The DEX program ID (raw, on-chain).                                                                                                          |
| `trader_id`                 | string  | no       | The swap instruction's own payer/owner account. See [field notes](#field-notes).                                                             |
| `tx_id`                     | string  | no       | Transaction signature.                                                                                                                       |
| `instruction_index`         | int64   | no       | Index of the swap instruction within the flattened instruction list.                                                                         |
| `parent_instruction_index`  | int64   | yes      | Parent instruction index when invoked by a router (inner instruction); `null` for a top-level swap.                                          |

### Field notes

* **`token_bought_*` vs `token_sold_*`** — direction is from the trader's perspective. A row always has both sides populated; `token_bought_amount` and `token_sold_amount` are the decimal-scaled versions of the `_raw` integer amounts.
* **`trade_source`** — distinguishes direct DEX interactions from router-routed ones. When a swap is an inner instruction of an aggregator, this holds the parent (router) program ID rather than `direct`.
* **`trader_id`** — the payer/owner account attached to the swap instruction itself. For router-routed swaps this is typically the router-owned account that signed the inner instruction, not necessarily the end user that submitted the transaction. Use `tx_id` plus the outer transaction's fee payer if you need the originating wallet.
* **`project` vs `project_main_id`** — use `project` for human-readable filters and grouping; use `project_main_id` when you need the exact on-chain program ID.

## Guide: Stream swaps from selected DEXes to Postgres

This pipeline streams Raydium CLMM and Orca Whirlpool swaps. `filter.program_ids` narrows the source at scan time; `options.dex` tells the decoder which DEX projects to emit.

```yaml theme={null}
name: solana-dex-swaps
resource_size: m

sources:
  dex_swaps:
    type: dataset
    dataset_name: solana.dex_swaps
    version: 1.0.0
    start_block: 426725306
    filter:
      program_ids: whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc,CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK
    options:
      dex: raydium_clmm,orca_whirlpool

sinks:
  postgres_swaps:
    type: postgres
    from: dex_swaps
    schema: public
    table: solana_dex_swaps
    secret_name: MY_POSTGRES
    primary_key: id
```

## Guide: Filter to a single DEX

Narrow both the source filter and the decoder options to a single DEX — here, Raydium CLMM:

```yaml theme={null}
name: raydium-clmm-swaps
resource_size: s

sources:
  dex_swaps:
    type: dataset
    dataset_name: solana.dex_swaps
    version: 1.0.0
    start_block: 426725306
    filter:
      program_ids: CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK
    options:
      dex: raydium_clmm

transforms:
  raydium_clmm:
    type: sql
    primary_key: id
    sql: |
      SELECT
        id,
        block_slot,
        block_timestamp,
        trader_id,
        tx_id,
        token_bought_mint_address,
        token_sold_mint_address,
        token_bought_amount,
        token_sold_amount,
        trade_source
      FROM dex_swaps

sinks:
  postgres_raydium:
    type: postgres
    from: raydium_clmm
    schema: public
    table: raydium_clmm_swaps
    secret_name: MY_POSTGRES
    primary_key: id
```

## Guide: Separate direct swaps from router-routed swaps

Aggregators like Jupiter invoke DEX programs as inner instructions. Use `trade_source` to split direct swaps from aggregator flow:

```yaml theme={null}
name: dex-swaps-by-source
resource_size: m

sources:
  dex_swaps:
    type: dataset
    dataset_name: solana.dex_swaps
    version: 1.0.0
    start_block: 426725306
    filter:
      program_ids: whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc,CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK
    options:
      dex: raydium_clmm,orca_whirlpool

transforms:
  categorized_swaps:
    type: sql
    primary_key: id
    sql: |
      SELECT
        id,
        project,
        tx_id,
        trader_id,
        token_bought_mint_address,
        token_sold_mint_address,
        token_bought_amount,
        token_sold_amount,
        CASE
          WHEN trade_source = 'direct' THEN 'direct'
          ELSE 'router'
        END AS swap_kind,
        trade_source AS router_program_id,
        block_slot,
        block_timestamp
      FROM dex_swaps

sinks:
  postgres_categorized:
    type: postgres
    from: categorized_swaps
    schema: public
    table: solana_dex_swaps_categorized
    secret_name: MY_POSTGRES
    primary_key: id
```

## Guide: Track swaps involving a specific token

Filter by mint on either side of the trade — for example, all Raydium CLMM and Orca Whirlpool swaps involving USDC:

```yaml theme={null}
name: usdc-dex-swaps
resource_size: s

sources:
  dex_swaps:
    type: dataset
    dataset_name: solana.dex_swaps
    version: 1.0.0
    start_block: 426725306
    filter:
      program_ids: whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc,CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK
    options:
      dex: raydium_clmm,orca_whirlpool

transforms:
  usdc_swaps:
    type: sql
    primary_key: id
    sql: |
      SELECT
        id,
        project,
        tx_id,
        trader_id,
        token_bought_mint_address,
        token_sold_mint_address,
        token_bought_amount,
        token_sold_amount,
        block_slot,
        block_timestamp
      FROM dex_swaps
      WHERE token_bought_mint_address = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'
         OR token_sold_mint_address   = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'

sinks:
  postgres_usdc_swaps:
    type: postgres
    from: usdc_swaps
    schema: public
    table: usdc_dex_swaps
    secret_name: MY_POSTGRES
    primary_key: id
```

<Tip>
  Keep `filter.program_ids` and `options.dex` in sync — `filter.program_ids` scopes which slots are scanned during backfills (see [Filtering by Account or Program](/turbo-pipelines/sources/solana#filtering-by-account-or-program)), and `options.dex` controls which decoded DEX projects are emitted. Listing a DEX in one but not the other will either scan more slots than needed or drop rows you expected.
</Tip>
