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

# Land Trades with Sender

> Build a low-latency send loop with Helius Sender: regional endpoints, connection warming, dynamic priority fees, tips, and landing confirmation with retries.

Sender simultaneously submits your transaction across every high-speed pathway (Helius, Jito, Harmonic, Rakurai) and consumes no API credits. You pay per send with a SOL tip. This guide builds a production send loop with warm connections, live-priced fees, and confirmation with a retry policy.

## Pick your tier

[Sender Max](/docs/sending-transactions/sender-max) (0.001 SOL minimum tip) routes across all pathways and enters the priority tip buffer, where a larger tip lands first.

[SWQOS-only](/docs/sending-transactions/sender-swqos-only) (0.000005 SOL) takes a single fast path for cost-optimized flow. Add `?swqos_only=true` to the endpoint URL.

Tips between the two minimums are best-effort through fewer pathways, so choose one tier or the other.

## Choose your endpoint

Backends should use the regional HTTP endpoint closest to their servers (`http://ewr-sender.helius-rpc.com/fast`, `fra`, `slc`, `ams`, `lon`, `sg`, `tyo`).

Browsers should use the global HTTPS endpoint `https://sender.helius-rpc.com/fast`, which auto-routes and avoids CORS issues.

## Warm the connection

A cold TCP/TLS handshake adds latency to the first send after an idle period.

If your system can go more than about 5 seconds between sends, keep the connection warm with the ping endpoint:

```typescript theme={"system"}
const SENDER = 'http://ewr-sender.helius-rpc.com';

setInterval(async () => {
  try {
    await fetch(`${SENDER}/ping`);
  } catch (e) {
    console.warn('warm-up failed:', e);
  }
}, 5_000);
```

## Build the transaction

Every Sender transaction must include both a tip transfer to a designated tip account and a compute unit price. Sender rejects transactions missing either one.

Hardcoding the priority fee leaves you overpaying in quiet markets and losing races in busy ones, so price it from the [Priority Fee API](/docs/priority-fee-api):

```typescript send.ts theme={"system"}
import {
  Connection, TransactionMessage, VersionedTransaction,
  SystemProgram, PublicKey, Keypair, ComputeBudgetProgram, LAMPORTS_PER_SOL
} from '@solana/web3.js';

const RPC = 'https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY';
const TIP_ACCOUNTS = [
  '4ACfpUFoaSD9bfPdeu6DBt89gB6ENTeHBXCAi87NhDEE',
  'D2L6yPZ2FmmmTKPgzaMKdhu6EWZcTpLy1Vhx8uvZe7NZ',
  '9bnz4RShgq1hAnLnZbP8kbgBg1kEmcJBYQq3gQbmnSta'
];

async function buildTransaction(keypair: Keypair, tradeInstructions: any[]) {
  const connection = new Connection(RPC);
  const { blockhash } = await connection.getLatestBlockhash('confirmed');

  // Price the fee against the accounts the trade touches
  const feeRes = await fetch(RPC, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      jsonrpc: '2.0', id: '1', method: 'getPriorityFeeEstimate',
      params: [{
        accountKeys: tradeInstructions.flatMap(ix => ix.keys.map((k: any) => k.pubkey.toBase58())),
        options: { recommended: true }
      }]
    })
  });
  const { result } = await feeRes.json();

  const tx = new VersionedTransaction(
    new TransactionMessage({
      instructions: [
        ComputeBudgetProgram.setComputeUnitLimit({ units: 100_000 }),
        ComputeBudgetProgram.setComputeUnitPrice({ microLamports: result.priorityFeeEstimate }),
        ...tradeInstructions,
        SystemProgram.transfer({
          fromPubkey: keypair.publicKey,
          toPubkey: new PublicKey(TIP_ACCOUNTS[Math.floor(Math.random() * TIP_ACCOUNTS.length)]),
          lamports: 0.001 * LAMPORTS_PER_SOL // Sender Max minimum; tip more to land first
        })
      ],
      payerKey: keypair.publicKey,
      recentBlockhash: blockhash
    }).compileToV0Message()
  );
  tx.sign([keypair]);
  return tx;
}
```

The tip determines which pathways your transaction can take, and the priority fee raises its position in the validator queue. Together they maximize inclusion probability.

## Send, then confirm

Submit with `skipPreflight: true` to trade client-side validation for latency, then confirm through your RPC connection.

Sender returns the signature immediately, which is not proof of landing:

```typescript theme={"system"}
async function sendAndConfirm(tx: VersionedTransaction): Promise<string> {
  const signature = await send(tx);

  const connection = new Connection(RPC);
  for (let i = 0; i < 30; i++) {
    const { value } = await connection.getSignatureStatuses([signature]);
    const status = value[0];
    if (status?.err) throw new Error(`Transaction failed: ${JSON.stringify(status.err)}`);
    if (status?.confirmationStatus === 'confirmed' || status?.confirmationStatus === 'finalized') {
      return signature;
    }
    await new Promise(r => setTimeout(r, 1_000));
  }
  throw new Error('Not confirmed within 30s: rebuild with a fresh blockhash and resend');
}

async function send(tx: VersionedTransaction): Promise<string> {
  const res = await fetch(`${SENDER}/fast`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      jsonrpc: '2.0',
      id: Date.now().toString(),
      method: 'sendTransaction',
      params: [
        Buffer.from(tx.serialize()).toString('base64'),
        { encoding: 'base64', skipPreflight: true, maxRetries: 0 }
      ]
    })
  });
  const json = await res.json();
  if (json.error) throw new Error(json.error.message);
  return json.result;
}
```

With `maxRetries: 0` you own the retry policy: when confirmation times out, rebuild with a fresh blockhash and a re-priced fee instead of resending the stale transaction.

Default throughput is 50 TPS. Professional plans can [request higher limits](https://www.helius.dev/contact).

## Optional: route around sandwich attackers

Add `?mev-protect=true` to the endpoint URL to avoid validators statistically linked to sandwich attacks. The request body is unchanged, and it works on both tiers:

```text theme={"system"}
http://ewr-sender.helius-rpc.com/fast?mev-protect=true
```

See [MEV Protect](/docs/sending-transactions/mev-protect) for the tradeoffs. For atomic multi-transaction execution (up to 4 transactions, all-or-nothing), use [`sendBundle`](/docs/sending-transactions/sender-max#bundles) on the same endpoint.

## Related guides

<CardGroup cols={2}>
  <Card title="Sender overview" icon="paper-plane" href="/docs/sending-transactions/sender">
    Tiers, endpoints, tip accounts, and rate limits in full
  </Card>

  <Card title="Trade on Preconfirmations" icon="stopwatch" href="/docs/pre-confirmations/guides/trade-on-preconfirmations">
    Pair the fastest send path with the earliest transaction signal
  </Card>
</CardGroup>
