End-to-end example
This script puts the pieces together in Paper Trading, so it never touches real funds:
- Checks the session token.
- Turns Paper Trading on and finds a paper Solana wallet.
- Streams a token’s price.
- Buys once, confirms the buy, then sells everything once the price is 20% up.
It needs Node.js 18 or newer (for the built-in fetch) and the ws package.
npm install ws
export NEURO_API=https://api.neurotrading.io/api/v1
export NEURO_WS=wss://socket.neurotrading.io
export NEURO_TOKEN='...' # see Authentication
export TOKEN_ADDRESS='Bp8m...pump' # the token to trade
node bot.mjsThis is a teaching example, not a strategy. It has no stop-loss and makes no attempt to handle partial fills or a restart. Do not point it at production with real funds without making it yours first.
// bot.mjs
import WebSocket from "ws";
const { NEURO_API, NEURO_WS, NEURO_TOKEN, TOKEN_ADDRESS } = process.env;
const BUY_SOL = 0.1;
const TAKE_PROFIT = 1.2; // sell everything at +20%
// ── REST helper: unwraps { data } and throws the API's own error message ──────────────
async function api(method, path, body) {
const res = await fetch(`${NEURO_API}${path}`, {
method,
headers: { Authorization: `Bearer ${NEURO_TOKEN}`, "Content-Type": "application/json" },
body: body === undefined ? undefined : JSON.stringify(body),
});
const json = await res.json().catch(() => ({}));
if (!res.ok) throw new Error(`${res.status} ${json.error?.message ?? json.message ?? res.statusText}`);
return json.data;
}
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
// Solana trades return at submission — poll until the network has a verdict.
async function confirm(txId) {
for (let i = 0; i < 60; i++) {
const { status, onChainError } = await api("GET", `/tradings/${txId}/status`);
if (status === "success") return;
if (status === "failed") throw new Error(`transaction failed: ${JSON.stringify(onChainError)}`);
await sleep(2000);
}
throw new Error("transaction not confirmed after 2 minutes");
}
// ── 1. Who am I? ───────────────────────────────────────────────────────────────────────
const user = await api("GET", "/user");
console.log("signed in as", user.username ?? user._id);
// ── 2. Paper Trading on, and a paper wallet to trade from ─────────────────────────────
await api("POST", "/demo/mode", { mode: "demo" });
const status = await api("GET", "/demo/status");
if (!status.enabled) throw new Error("Paper Trading did not turn on — refusing to trade for real");
const wallets = await api("GET", "/wallets?chainId=101&includeBalance=true");
const wallet = wallets[0];
if (!wallet) throw new Error("no Solana paper wallet found");
console.log("trading from paper wallet", wallet.publicKey);
// ── 3 & 4. Stream the price, buy once, sell at the target ─────────────────────────────
let entryPrice = null;
let state = "idle"; // idle → buying → holding → selling → done
const ws = new WebSocket(NEURO_WS);
ws.on("open", () => ws.send(JSON.stringify({ type: "subscribe", contractAddresses: [TOKEN_ADDRESS] })));
ws.on("message", async (raw) => {
const msg = JSON.parse(raw.toString());
if (msg.type !== "price_update" || msg.data.metricsUpdatedAt !== undefined) return;
const price = Number(msg.data.priceNative); // SOL per token
console.log(`${msg.data.symbol}: ${price} SOL`);
try {
if (state === "idle") {
state = "buying";
const buy = await api("POST", "/tradings/buy", {
walletAddress: wallet.publicKey,
tokenAddress: TOKEN_ADDRESS,
amount: BUY_SOL,
slippage: 15,
});
await confirm(buy.txId);
entryPrice = price;
state = "holding";
console.log(`bought at ~${entryPrice} SOL (${buy.txId})`);
} else if (state === "holding" && price >= entryPrice * TAKE_PROFIT) {
state = "selling";
const sell = await api("POST", "/tradings/sell", {
walletAddress: wallet.publicKey,
tokenAddress: TOKEN_ADDRESS,
amount: 100,
slippage: 15,
});
await confirm(sell.txId);
state = "done";
console.log(`sold at ~${price} SOL (${sell.txId})`);
ws.close();
}
} catch (err) {
console.error(err.message);
// Go back one step so the next tick can try again.
state = state === "buying" ? "idle" : state === "selling" ? "holding" : state;
}
});
ws.on("close", () => console.log("stream closed"));Going live
When the script behaves in Paper Trading:
- Switch the account back with
POST /demo/modeand{"mode": "real"}. - Remove the Paper Trading step, and replace it with a check that
GET /demo/statusreportsenabled: false, so the script knows it is trading for real. - Use a wallet that holds only what you are prepared to lose to a bug.
Last updated on