in-solana by Supanode

Parse DEX Swaps From a Transaction Stream

TL;DR

  • - Subscribe to transactions involving DEX program IDs
  • - Identify swap instructions by discriminator bytes
  • - Extract amounts from pre/post token balances, not instruction data
  • - Handle CPI-based swaps from aggregators like Jupiter

Parsing DEX swaps from a Solana transaction stream requires subscribing to transactions that involve DEX program accounts, then extracting swap details from the transaction data.

Subscribe to DEX transactions

Filter for transactions involving major DEX programs:

{
  "transactions": {
    "dex_swaps": {
      "vote": false,
      "failed": false,
      "accountInclude": [
        "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8",
        "whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc"
      ],
      "accountExclude": []
    }
  },
  "commitment": 0
}

Extracting swap amounts

The most reliable way to determine swap amounts is from pre/post token balances, not from instruction data. Token balances are provided in the transaction metadata.

preTokenBalances: [
  { mint: "So11...", owner: "USER...", uiAmount: 1.5 },
  { mint: "EPjF...", owner: "USER...", uiAmount: 0 }
]
postTokenBalances: [
  { mint: "So11...", owner: "USER...", uiAmount: 0.5 },
  { mint: "EPjF...", owner: "USER...", uiAmount: 1000 }
]

The user spent 1.0 SOL and received 1000 tokens. This works regardless of the DEX program’s instruction encoding.

Handling aggregator swaps

Jupiter and other aggregators route swaps through multiple DEX programs via CPI. A single user transaction may contain inner instructions across several pools.

To catch aggregator swaps, either:

  1. Subscribe to transactions involving the aggregator program, then parse inner instructions
  2. Subscribe broadly and check pre/post token balances for the user’s accounts

Option 2 is simpler and catches all swap paths regardless of routing.

Identifying the swap direction

For each transaction, find the user’s address (typically the first signer). Compare their pre and post token balances:

  • Token balance decreased → the user sold this token
  • Token balance increased → the user bought this token
  • SOL balance decreased beyond fees → the user sold SOL

Common pitfalls

Don’t rely on instruction data format. Each DEX encodes swap parameters differently. Raydium, Orca, and Meteora all have different instruction layouts. Token balance diffs are universal.

Account for fees. SOL balance decreases include transaction fees (base fee + priority fee). Subtract the fee before calculating SOL swap amounts.

Handle partial fills. Some DEX programs may partially fill orders. The actual amounts are in the balances, not the requested amounts in instruction data.

FAQ

How do I get the token price from a swap? Divide the output amount by the input amount. For a swap of 1 SOL → 1000 TOKEN, the price is 1000 TOKEN/SOL. Use the token decimals to convert raw amounts.

Do I need different parsers for each DEX? For basic swap detection (who swapped what for what), the token balance approach is universal. For advanced data (pool address, price impact, route), you need DEX-specific parsing.

How do I handle wrapped SOL? Many DEXes wrap SOL into a temporary token account for the swap. Watch for the native mint (So11111111111111111111111111111111111111112) in token balances. The wrapping and unwrapping happen within the transaction.

Updated: