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

# Solana: MEV protection with Jito

> Protect Solana transactions from sandwich attacks using Jito dontfront, Chainstack Warp transactions, and Trader Nodes for MEV-resistant execution.

**TLDR:**

* Sandwich attacks front-run and back-run your transaction within the same bundle, extracting value at your expense.
* Jito's `dontfront` feature prevents this by ensuring your transaction must appear at index 0 in any bundle.
* You add a pubkey starting with `jitodontfront` as a read-only account to any instruction, then send through Jito's block engine.
* Chainstack [Warp transactions](/docs/warp-transactions) optimize for **speed** (bloXroute relay). Jito `dontfront` optimizes for **protection**. Choose based on your use case.

## What is a sandwich attack?

A sandwich attack is when a searcher:

1. **Front-runs** your swap by buying the same token before you, pushing the price up
2. Your transaction executes at the inflated price
3. **Back-runs** by selling immediately after, profiting from the price difference

This happens at the bundle level — the attacker places their transactions around yours in the same block. The result: you get worse execution, the attacker takes the difference.

## How Jito `dontfront` works

Jito's block engine processes transaction bundles. The `dontfront` feature is a simple opt-in:

1. Add a pubkey starting with `jitodontfront` (e.g., `jitodontfront111111111111111111111111111111`) as a **read-only account** to any instruction in your transaction
2. Send the transaction through Jito's block engine endpoint (not a standard RPC)
3. The block engine enforces that your transaction must be at **index 0** in any bundle that includes it

Since the attacker's front-running transaction can't appear before yours in the bundle, the sandwich is impossible.

<Warning>
  This feature requires sending transactions through Jito's block engine, not standard RPC nodes. The Jito endpoint is `https://mainnet.block-engine.jito.wtf/api/v1/transactions`.
</Warning>

<Check>
  ### Get your own node endpoint today

  [Start for free](https://console.chainstack.com/) and get your app to production levels immediately. No credit card required.

  You can sign up with your GitHub, X, Google, or Microsoft account.
</Check>

## Implementation

### Prerequisites

```bash theme={"system"}
npm install @solana/web3.js dotenv
```

### Add `dontfront` protection to a transaction

<CodeGroup>
  ```typescript TypeScript theme={"system"}
  import {
    Connection,
    Keypair,
    PublicKey,
    SystemProgram,
    TransactionMessage,
    VersionedTransaction,
    TransactionInstruction,
    LAMPORTS_PER_SOL,
  } from "@solana/web3.js";
  import bs58 from "bs58";
  import "dotenv/config";

  // Use your Chainstack endpoint for reads
  const connection = new Connection(process.env.SOLANA_RPC!);
  const payer = Keypair.fromSecretKey(bs58.decode(process.env.PRIVATE_KEY!));

  // Jito block engine for sends
  const JITO_ENDPOINT =
    "https://mainnet.block-engine.jito.wtf/api/v1/transactions";

  // Any valid pubkey starting with "jitodontfront". Does not need to exist on-chain.
  const DONT_FRONT = new PublicKey(
    "jitodontfront111111111111111111111111111111"
  );

  // Jito tip accounts — pick one at random to reduce contention
  const TIP_ACCOUNTS = [
    "96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5",
    "HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe",
    "Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY",
    "ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49",
    "DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh",
    "ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt",
    "DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL",
    "3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT",
  ];

  function addDontFront(instruction: TransactionInstruction): TransactionInstruction {
    return new TransactionInstruction({
      ...instruction,
      keys: [
        ...instruction.keys,
        { pubkey: DONT_FRONT, isSigner: false, isWritable: false },
      ],
    });
  }

  function randomTipAccount(): PublicKey {
    const idx = Math.floor(Math.random() * TIP_ACCOUNTS.length);
    return new PublicKey(TIP_ACCOUNTS[idx]);
  }

  async function sendWithMEVProtection() {
    const latestBlockhash = await connection.getLatestBlockhash();

    // Your actual instruction — add dontfront to it
    const transferIx = addDontFront(
      SystemProgram.transfer({
        fromPubkey: payer.publicKey,
        toPubkey: payer.publicKey,
        lamports: 0.001 * LAMPORTS_PER_SOL,
      })
    );

    // Jito tip — minimum 1000 lamports
    const tipIx = SystemProgram.transfer({
      fromPubkey: payer.publicKey,
      toPubkey: randomTipAccount(),
      lamports: 1000,
    });

    const message = new TransactionMessage({
      payerKey: payer.publicKey,
      recentBlockhash: latestBlockhash.blockhash,
      instructions: [transferIx, tipIx],
    }).compileToV0Message();

    const transaction = new VersionedTransaction(message);
    transaction.sign([payer]);

    // Send through Jito block engine, NOT standard RPC
    const serialized = Buffer.from(transaction.serialize()).toString("base64");
    const response = await fetch(JITO_ENDPOINT, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        jsonrpc: "2.0",
        id: 1,
        method: "sendTransaction",
        params: [serialized, { encoding: "base64" }],
      }),
    });

    const result = await response.json();
    console.log("Sent with dontfront protection:", result.result);
  }

  sendWithMEVProtection();
  ```
</CodeGroup>

## Chainstack Warp transactions vs Jito `dontfront`

Chainstack offers two transaction acceleration paths. They serve different purposes:

|                              | [Warp transactions](/docs/warp-transactions) | Jito `dontfront`                                       |
| ---------------------------- | -------------------------------------------- | ------------------------------------------------------ |
| **Goal**                     | Maximum speed — fastest landing              | MEV protection — prevent sandwich                      |
| **Mechanism**                | bloXroute relay for optimized propagation    | Jito block engine enforces bundle index 0              |
| **Endpoint**                 | Your Chainstack RPC (with Warp enabled)      | Jito block engine (`mainnet.block-engine.jito.wtf`)    |
| **Front-running protection** | No — speed-optimized, protection disabled    | Yes — core feature                                     |
| **Tip required**             | No                                           | Yes (minimum 1000 lamports)                            |
| **Best for**                 | Arbitrage, sniping, latency-sensitive trades | Swaps, DeFi interactions where execution price matters |

**Use Warp** when you need to land first (you are the one competing for position).
**Use `dontfront`** when you need to protect your execution price (others are competing against you).

For reads (getAccountInfo, getBlock, etc.), always use your [Chainstack Solana endpoint](/docs/solana-tooling).

## Tips

* **Jito tip amounts** should be minimum 1000 lamports. For `sendTransaction`, use a 70/30 split between priority fee and Jito tip.
* **Pick tip accounts at random** to reduce contention across the 8 Jito tip accounts.
* When using `sendBundle`, `dontfront` transactions must be contiguous at the front of the bundle with overlapping signers.
* `dontfront` is **mainnet and testnet only** — it does not work on devnet.

## Additional resources

* [Solana Trader Nodes with Warp transactions](/docs/solana-trader-nodes) — Chainstack's speed-optimized transaction path
* [Priority fees for faster transactions](/docs/solana-how-to-priority-fees-faster-transactions) — set optimal priority fees
* [How to handle the transaction expiry error](/docs/solana-how-to-handle-the-transaction-expiry-error) — retry logic
