Skip to main content

Copy trade

Follow one or more wallets, buy what they buy, sell when they sell. The Advanced Data Stream shows every trade of a wallet on every launchpad we index, and Lightspeed mirrors it in one request.

What you need​

  • Node.js 22 or newer, npm install socket.io-client.
  • A funded Lightspeed account.
  • Wallets to follow. The stream itself is the place to find them: watch a few launches, note who buys early and sells in profit.

The script​

import { io } from "socket.io-client";

// ─── change these ─────────────────────────────────────
const LS_KEY = "ls_…";
const FOLLOW = ["WALLET_1", "WALLET_2"]; // wallets to copy
const COPY_RATIO = 0.1; // copy 10% of their size ...
const MIN_SOL = 0.01; // ... but at least this
const MAX_SOL = 0.5; // ... and at most this
const SLIPPAGE = 10;
const TIP = 0.0007;
const MAX_OPEN = 8;
const DRY_RUN = true;
// ──────────────────────────────────────────────────────

const API = "https://sol.shrine.trade";
const follow = new Set(FOLLOW);
const open = new Map(); // mint -> { from }

async function lightspeed(body) {
if (DRY_RUN) { console.log(" dry-run", body); return { success: true }; }
const r = await (await fetch(`${API}/api/lightspeed`, {
method: "POST", headers: { "content-type": "application/json", "x-api-key": LS_KEY }, body: JSON.stringify(body),
})).json();
if (!r.success) throw new Error(`${r.error}: ${r.message}`);
return r;
}

const socket = io(API, { transports: ["websocket"] });
socket.on("connect", () => {
// Trades only, every launchpad; the filter below picks the wallets.
socket.emit("subscribe_stream", { actions: ["buy", "sell"] });
console.log("following", FOLLOW.join(", "));
});

socket.on("stream", async (e) => {
// One stream event per transaction; `breakdown` lists each trader's leg.
// A followed wallet's leg is what we copy, whatever router it went through.
const leg = (e.breakdown || []).find((b) => follow.has(b.trader));
if (!leg) return;
if (leg.action === "buy") {
if (open.has(e.mint) || open.size >= MAX_OPEN) return;
const sol = Math.min(MAX_SOL, Math.max(MIN_SOL, leg.quoteAmount * COPY_RATIO));
console.log(`${leg.trader.slice(0, 6)} bought ${e.mint.slice(0, 6)} for ${leg.quoteAmount} SOL -> copying ${sol}`);
try {
await lightspeed({ action: "buy", mint: e.mint, amount: sol, slippage: SLIPPAGE, tip: TIP });
open.set(e.mint, { from: leg.trader });
} catch (err) {
console.error(` buy failed: ${err.message}`);
}
} else if (leg.action === "sell" && open.has(e.mint)) {
console.log(`${leg.trader.slice(0, 6)} sold ${e.mint.slice(0, 6)}`);
open.delete(e.mint);
try {
await lightspeed({ action: "sell", mint: e.mint, amount: "100%", slippage: SLIPPAGE, tip: TIP });
} catch (err) {
console.error(` sell failed: ${err.message}`);
}
}
});

What each part does​

  • Matching on the breakdown, not on txSigner: most trades go through a router, so the signer is the router's payer and the wallet you follow is the trader inside the breakdown. Matching there copies trades sent through any bot.
  • Sizing by ratio with a floor and a cap: a whale's 20 SOL becomes 0.5, a 0.05 SOL probe becomes 0.01. Change the rule to a fixed size if you prefer.
  • Partial sells. The script closes the whole position on the first sell it sees. To mirror partial exits, compare leg.tokenAmount with the wallet's balance before the trade and sell the same fraction.
  • Quoted coins. A coin priced in USDC or a stock is bought with SOL on Lightspeed; amount stays SOL. The response's quoteMint says what it settled in.

Being first behind them​

Your copy lands a slot or two after the trade it copies, behind everyone else copying the same wallet. Two things shorten that: run in the region closest to you, and raise tip on the copies that matter. For launches specifically, the sniper guide shows the Ultra Fast Stream feed, which also carries wallet filters (wallets=): the same copy, a block earlier, before the trade has executed.

Finding wallets worth following​

The stream has what you need. Keep a map of trader → buys on launches under a minute old, and their sells; after a day, rank by realised profit. Wallets that are early and that sell are the ones to copy; wallets that only buy are bags.