Solana Copy Trading API: Detect, Decide, Land

How copy trading works on Solana: detecting a wallet's swap, deciding whether to follow, and landing your own transaction before the price moves.

BoltTx Team··10 min read
solanacopy-tradingtrading-bottransaction-landingwebsocketrpc

Copy trading sounds like a data problem. Watch a wallet, see what it buys, buy the same thing.

In practice it is a latency problem wearing a data problem's clothes. By the time you have detected the trade, decided to follow it, and landed your own transaction, the price has moved — and how much it moved is the entire margin.

There Is No Copy Trading API

Nothing exposes "tell me when this wallet trades." You assemble it from three pieces:

Detection. Watch a set of wallets for swap activity. Decision. Decide whether this particular trade is worth following. Execution. Build and land your own transaction.

Most guides spend their length on the first piece. ★The third is where the money goes.★

If detection already works and you just need the execution half, a free BoltTx key is one line. The rest of this is the parts you build yourself.

Detection: Three Options

Polling signatures

Call getSignaturesForAddress for each wallet on a timer, diff against what you saw last time.

async function pollWallet(connection: Connection, wallet: PublicKey, seen: Set<string>) {
  const sigs = await connection.getSignaturesForAddress(wallet, { limit: 10 });
  // ★getSignaturesForAddress returns newest-first — replay oldest-first★
  const fresh = sigs.filter((s) => !seen.has(s.signature) && !s.err).reverse();
  fresh.forEach((s) => seen.add(s.signature));
  return fresh;
}

Simple. Also the slowest option, and it scales badly — 50 wallets on a one-second timer is 50 requests per second before you have parsed anything.

Log subscriptions

Subscribe over WebSocket — logsSubscribe for program activity, accountSubscribe for a specific account — and get pushed events instead of asking for them.

const sub = connection.onLogs(
  wallet,
  (logs) => {
    if (logs.err) return; // failed transaction, nothing to copy
    handleActivity(logs.signature);
  },
  "processed", // "confirmed" costs a slot or more you cannot get back
);

★Use processed, not confirmed.★ Waiting for confirmation is waiting for the thing you are racing. You take on the risk that the transaction gets dropped, which you handle by verifying before acting rather than by waiting.

Geyser-style streaming

A dedicated stream of account and transaction updates. Fastest, most work to run, and usually a paid service.

Decision: What to Actually Copy

Detection gives you a signature. Now you need to know what happened and whether to follow it.

const tx = await connection.getParsedTransaction(signature, {
  maxSupportedTransactionVersion: 0,
});

// Balance deltas are more reliable than parsing instructions,
// because they work the same across every DEX and router.
const pre = tx.meta.preTokenBalances ?? [];
const post = tx.meta.postTokenBalances ?? [];

Reading balance deltas rather than decoding instructions is worth the small extra effort. ★Every DEX and aggregator has its own instruction layout, and they change. Balance deltas do not.★

The filters that matter more than people expect:

Size relative to the wallet. A trader putting 0.5% of their book into something is not making the same statement as one putting 20% in. Copying both identically means copying a signal you did not read correctly.

Is this an entry or an exit? A buy in a token they already hold is averaging in. A buy in something new is a new position. Different meaning, different urgency.

Token age and liquidity. A trade into a pool with thin liquidity will move against you when you follow it, because your own trade is a meaningful share of the depth.

Have they done this before? A wallet that buys and sells the same token every hour is running a strategy you cannot copy by following individual trades.

Execution: Where the Margin Is Won or Lost

Here is the arithmetic that decides whether a copy trading bot works.

The trader you follow bought at some price. You buy N slots later, at a price that has moved because their trade moved it — and because everyone else copying the same wallet is also buying.

★Your entry is worse than theirs by construction.★ The question is only by how much, and that is a function of how many slots you take.

At Solana's slot cadence, that works out to:

Slots behind Time behind
2 under a second
5 around two seconds
10 around four seconds

On a token that just got a large buy, four seconds is a long time.

Reducing it means the same three things that decide any Solana submission:

import { ComputeBudgetProgram } from "@solana/web3.js";

// Fees are contested per account. Query with the accounts you write.
const recent = await connection.getRecentPrioritizationFees({
  lockedWritableAccounts: writableAccounts,
});
const fees = recent.map((r) => r.prioritizationFee).sort((a, b) => a - b);
const median = fees[Math.floor(fees.length / 2)] ?? 0;

instructions.unshift(
  ComputeBudgetProgram.setComputeUnitPrice({
    microLamports: Math.max(median * 2, 5_000),
  }),
  ComputeBudgetProgram.setComputeUnitLimit({ units: 200_000 }),
);

Plus continuous retry until the blockhash expires, and a submission path that does not get deprioritised when block space is contested.

The Slippage Trap

Copy trading has a specific failure mode worth naming.

You detect a buy, you follow it, and your slippage tolerance is set to something reasonable like 1%. But the trade you are copying already moved the price 3%, and the other copiers moved it another 2%. Your transaction fails on slippage.

So you widen the tolerance to 10%. Now you fill — at a price 8% worse than the wallet you are copying, on a position they may exit at 5% profit.

★Both outcomes lose. The fix is not the tolerance, it is the slot count.★

If you are consistently landing five or more slots behind, no slippage setting makes the strategy work. Tolerance is a symptom dial; latency is the actual variable.

What Landing Looks Like

Real transactions through our delivery nodes: median confirmation 336ms — under one slot.

Two slots is under a second behind the wallet you are following, before your own detection and decision time. That is the budget you are working inside.

Measuring Whether It Works

Track the gap, not the fills. A bot that fills every trade at a bad price looks healthy in a fill-rate dashboard and loses money.

log({
  sourceWallet,
  sourceSlot,      // slot where their transaction landed
  ourSlot,         // slot where ours landed
  slotGap: ourSlot - sourceSlot,
  sourcePrice,
  ourPrice,
  entryGapBps: Math.round(((ourPrice - sourcePrice) / sourcePrice) * 10_000),
});

slotGap and entryGapBps together tell you everything.★ If the slot gap is small and the entry gap is still large, you are copying trades that move the market too much to follow. If the slot gap is large, that is an execution problem you can fix.

Where BoltTx Fits

We do the execution half. Not detection, not wallet analytics, not indexing.

Submissions route through our own delivery nodes in four regions with stake-weighted routing and no public mempool exposure, so a transaction is not observable in transit before it lands. You sign locally — we never hold funds, never sign, and never modify transaction contents.

The tip travels inside the transaction, paid on chain from your own wallet. If the transaction reverts, the tip reverts with it, because that is how Solana handles atomic transactions. You pay only on transactions that reach the chain.

Get a free API key. No monthly fee:

// Pick the region closest to where your bot runs
const connection = new Connection("https://la.bolttx.io/?api-key=YOUR_KEY");

Then log slotGap for a week and see whether it moves.

FAQ

Is there a Solana copy trading API? No single endpoint does it. You assemble copy trading from three pieces: watching wallets for activity, parsing what they traded, and submitting your own transaction. The first two are read operations against any RPC; the third decides your margin.

How do I track a Solana wallet's trades in real time? Subscribe to the wallet's logs over WebSocket at the processed commitment. Polling getSignaturesForAddress also works but is slower and scales badly across many wallets.

How fast do I need to be for copy trading to work? Fast enough that the price has not moved past your edge. Two slots behind is under a second; ten slots is around four seconds, which on a token that just took a large buy is usually too late.

Why do my copy trades keep failing on slippage? Because the trade you are copying moved the price, and so did every other copier. Widening tolerance makes you fill at a worse price rather than fixing the cause. If you are five or more slots behind, the slot count is the problem.

How do I know what token a wallet bought? Read preTokenBalances and postTokenBalances from the parsed transaction and compute the delta. This works uniformly across DEXes and routers, unlike decoding instructions, which differ per program and change over time.

Should I copy every trade from a wallet? No. Filter by position size relative to their holdings, whether it is an entry or an add, and the liquidity of the token. Copying a 0.5% position and a 20% position identically means ignoring the signal you were trying to read.

What commitment level should I use for detection? processed, because waiting for confirmed costs a slot or more you cannot recover. You accept that a small fraction of what you see may get dropped, and you handle that by verifying before acting rather than by waiting.

Can I copy trade on Solana without running my own bot? Hosted services exist. The trade-off is that you inherit their latency and their filters, and you cannot see why a trade was or was not copied.

How many wallets can I watch at once? With WebSocket subscriptions, many — you are receiving pushes rather than making requests. With polling, you hit rate limits quickly, since each wallet is a separate request on every cycle.

Why does my bot fill at a much worse price than the wallet I follow? Your entry is worse by construction, since their trade moved the price before yours arrived. The size of the gap is a function of how many slots behind you land. Log both slot numbers and the price difference to see which part to fix.

Does copy trading work on newly launched tokens? It is hardest there. Thin liquidity means both the original trade and yours move the price significantly, and the gap between them is widest exactly when the token is newest.

What is the difference between copy trading and front running? Copy trading follows a trade after it has landed on chain. Front running acts on knowledge of a transaction before it is included. The first uses public information; the second depends on seeing something in transit.

How do I avoid copying a wallet's losing trades? You cannot know in advance. What you can do is filter on the characteristics of the trade — size, whether it is a new position, liquidity — and track your own performance per source wallet rather than in aggregate.

Do I need a WebSocket connection for copy trading? For detection, it is significantly faster than polling and scales better across many wallets. For submitting your own transaction, no — that is an HTTP call, and often through a different endpoint.

Why do my copy trades land but lose money anyway? Look at entry gap rather than fill rate. A bot that fills everything at a price 8% worse than its source wallet looks healthy on a fill-rate dashboard and still loses.

How do I pick which wallets to copy? Backtest against their history before following live. A wallet with good realised returns over hundreds of trades is a different proposition from one with a few large wins, and the second is far more common in leaderboards.

Back to all posts